home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / graphics / 3dvect37.zip / MATH.INC < prev    next >
Text File  |  1994-06-22  |  83KB  |  3,124 lines

  1. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2. ;
  3. ; Filename     : Math.inc
  4. ; Included from: 3D1.ASM, 3D2.ASM, 3D3.ASM
  5. ; Description  : General math functions.
  6. ;
  7. ; Written by: John McCarthy
  8. ;             1316 Redwood Lane
  9. ;             Pickering, Ontario.
  10. ;             Canada, Earth, Milky Way (for those out-of-towners)
  11. ;             L1X 1C5
  12. ;
  13. ; Internet/Usenet:  BRIAN.MCCARTHY@CANREM.COM
  14. ;         Fidonet:  Brian McCarthy 1:229/15
  15. ;   RIME/Relaynet: ->CRS
  16. ;
  17. ; Home phone, (905) 831-1944, don't call at 2 am eh!
  18. ;
  19. ; Send me your protected mode source code!
  20. ; Send me your Objects!
  21. ; But most of all, Send me a postcard!!!!
  22. ;
  23. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  24.  
  25.            public rotate        ; rotate using vmatrix
  26.            public make3d        ; calculate 3d ?actual*?/z ( both x and y)
  27.            public make3dx       ; xactual*x/z
  28.            public make3dy       ; yactual*y/z
  29.            public erotate       ; 32 bit rotate using ematrix
  30.            public zsolve        ; solve single equation variable
  31.            public ysolve
  32.            public xsolve
  33.            public cosign
  34.            public sign
  35.            public arctan
  36.            public compound      ; generate rotation matrix (includes camera)
  37.            public setsincose    ; set camera matrix
  38.            public temp_matrix   ; set user defined/temporary matrix
  39.            public temp_rotate   ; rotate point by temp matrix
  40.            public matrix_multiply ; multiply tmatrix by vmatrix
  41.  
  42.            public set_precal7
  43.            public set_precal147
  44.            public frotate
  45.  
  46.            public fzsolve
  47.            public fxsolve
  48.            public fysolve
  49.  
  50.            public precal1
  51.            public precal4
  52.            public precal7
  53.  
  54.            public sqrt          ; eax=sqr(eax), thanks to TRAN!
  55.            public _squareroot32 ; eax=sqr(eax)
  56.            public sqrax2bx2     ; ax = sqr(ax^2+bx^2)
  57.  
  58.            public pre_cal_lambert   ; scan object si and calculate surface normals
  59.            public calc_normal       ; guess...from 3 points, returns vector ebx,ecx,ebp
  60.            public calc_d            ; calculate D from plane equation
  61.            public lambert           ; calculate surface normal rotation matrix for object si
  62.            public set_up_all_lambert; scans objects from si to di and calls pre_cal_lambert
  63.            public lrotate           ; given normal for surface, figures out intensity
  64.  
  65.            public lx1               ; points to load up before calling calc_normal
  66.            public ly1
  67.            public lz1
  68.            public lx2
  69.            public ly2
  70.            public lz2
  71.            public lx3
  72.            public ly3
  73.            public lz3
  74.  
  75.            align 16
  76.  
  77. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  78. ;
  79. ; Rotate - 32 bit rotate point using vmatrix
  80. ; In:
  81. ;    EBX - x point
  82. ;    ECX - y point
  83. ;    EBP - z point
  84. ;     vmatrix - 32 bit rotation matrix - set up by "compound" routine
  85. ; Out:
  86. ;    EBX - x point
  87. ;    ECX - y point
  88. ;    EBP - z point
  89. ;
  90. ; Notes:
  91. ;
  92. ; All rotations (erotate,rotate,temp_rotate) are 32 bit.
  93. ; Frotate uses rotation along a plane and uses ematrix with precal147
  94. ;
  95. ; point rotation
  96. ; ebx = x   ecx = y   ebp = z    32 bit rotation!
  97. ; clobbers edx,esi,eax
  98. ;
  99. ; remember , matrix offsets are:
  100. ;
  101. ;  0 1 2     multiply those by 4 for the word address of the matrix
  102. ;  3 4 5
  103. ;  6 7 8
  104. ;
  105. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  106.  
  107. rotate:
  108.            mov eax,vmatrix+8    ; solve x = bx(0)+cx(1)+bp(2)
  109.            imul ebp
  110.            shrd eax,edx,14
  111.            mov edi,eax
  112.            mov eax,vmatrix+4
  113.            imul ecx
  114.            shrd eax,edx,14
  115.            add edi,eax
  116.            mov eax,vmatrix+0
  117.            imul ebx
  118.            shrd eax,edx,14
  119.            add edi,eax   ; di = new x
  120.  
  121.            mov eax,vmatrix+20   ; solve y = bx(3)+cx(4)+bp(5)
  122.            imul ebp
  123.            shrd eax,edx,14
  124.            mov esi,eax
  125.            mov eax,vmatrix+16
  126.            imul ecx
  127.            shrd eax,edx,14
  128.            add esi,eax
  129.            mov eax,vmatrix+12
  130.            imul ebx
  131.            shrd eax,edx,14
  132.            add esi,eax   ; si = new y
  133.  
  134.            mov eax,vmatrix+32   ; solve z = bx(6)+cx(7)+bp(8)
  135.            imul ebp
  136.            shrd eax,edx,14
  137.            mov ebp,eax
  138.            mov eax,vmatrix+28
  139.            imul ecx
  140.            shrd eax,edx,14
  141.            add ebp,eax
  142.            mov eax,vmatrix+24
  143.            imul ebx
  144.            shrd eax,edx,14
  145.            add ebp,eax   ; bp = new z
  146.  
  147.            mov ecx,esi
  148.            mov ebx,edi
  149.  
  150.            ret
  151.  
  152. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  153. ;
  154. ; Make3d - scale 3d point into 2d point
  155. ; In:
  156. ;    EBX - x point
  157. ;    ECX - y point
  158. ;    EBP - z point
  159. ; Out:
  160. ;    EBX - x point
  161. ;    ECX - y point
  162. ;    EBP - z point
  163. ;
  164. ; Notes:
  165. ;
  166. ; fast ratios found in macros.inc since
  167. ; multiplication has been substituted with fast lea
  168. ;
  169. ; trashes eax,edx,edi
  170. ;
  171. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  172.  
  173. make3d:                            ; bp must always be positive
  174.            cmul eax,ebx,ratiox     ; use fast constant multiply
  175.  
  176.            idiv ebp
  177.            mov ebx,eax
  178.  
  179. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  180. ;
  181. ; Make3dy - scale 3d point into 2d point on x axis only
  182. ; In:
  183. ;    ECX - y point
  184. ;    EBP - z point
  185. ; Out:
  186. ;    ECX - y point
  187. ;    EBP - z point
  188. ;
  189. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  190. make3dy:
  191.            cmul eax,ecx,ratioy
  192.  
  193.            idiv ebp
  194.            mov ecx,eax
  195.  
  196.            ret
  197.  
  198. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  199. ;
  200. ; Make3dx - scale 3d point into 2d point on y axis only
  201. ; In:
  202. ;    EDI - x point
  203. ;    ESI - z point
  204. ; Out:
  205. ;    EDI - x point
  206. ;    ESI - z point
  207. ;
  208. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  209.  
  210. make3dx:                           ; bp must always be positive
  211.            cmul eax,edi,ratiox
  212.  
  213.            idiv esi
  214.            mov edi,eax
  215.  
  216.            ret
  217.  
  218. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  219. ;
  220. ; Checkfront: checks if a side is visible. (counter-clockwise)
  221. ;
  222. ; In:
  223. ;   (EDI,EBP) - xy of point 1
  224. ;   (ESI,ECX) - xy of point 2
  225. ;   (EDX,EBX) - xy of point 3
  226. ; Out:
  227. ;   ECX < 0 if side counter-clockwise
  228. ;
  229. ; Notes: routine courtesy of "RAZOR"
  230. ; eg:
  231. ;          call checkfront
  232. ;          cmp ecx,0
  233. ;          jng dontdraw
  234. ;
  235. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  236.  
  237.  
  238.            align 16
  239.  
  240. checkfront:
  241.            cmp edi,esi
  242.            jng s cfc2
  243.            mov eax,edi
  244.            mov edi,esi
  245.            mov esi,edx
  246.            mov edx,eax
  247.            mov eax,ebp
  248.            mov ebp,ecx
  249.            mov ecx,ebx
  250.            mov ebx,eax
  251. cfc:
  252.            cmp edi,esi
  253.            jng s cfc2
  254.            mov eax,edi
  255.            mov edi,esi
  256.            mov esi,edx
  257.            mov edx,eax
  258.            mov eax,ebp
  259.            mov ebp,ecx
  260.            mov ecx,ebx
  261.            mov ebx,eax
  262. cfc2:
  263.            mov eax,edx               ; ax = x3
  264.            sub eax,edi               ; ax = x3 - x1
  265.            sub ecx,ebp               ; cx = y2 - y1
  266.            imul ecx                  ; ax = (x3-x1)*(y2-y1)
  267.            mov ecx,eax               ; save it...
  268.            mov eax,esi               ; ax = x2
  269.            sub eax,edi               ; ax = x2 - x1
  270.            sub ebx,ebp               ; bx = y3 - y1
  271.            imul ebx                  ; ax = (x2-x1)*(y3-y1)
  272.            sub ecx,eax               ; cx = (x3-x1)*(y2-y1)-(x2-x1)*(y3-y1)
  273.            ret
  274.  
  275. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  276. ;
  277. ; ERotate - 32 bit rotate point using ematrix
  278. ; In:
  279. ;    EBX - x point
  280. ;    ECX - y point
  281. ;    EBP - z point
  282. ;     ematrix - 32 bit rotation matrix - set up by "setsincose" routine
  283. ; Out:
  284. ;    EBX - x point
  285. ;    ECX - y point
  286. ;    EBP - z point
  287. ;
  288. ; Notes:
  289. ;
  290. ; point rotation for eye - solves all x,y,z parameters
  291. ; camera rotation is 32 bit and uses ematrix
  292. ;
  293. ; remember , matrix offsets are:
  294. ;
  295. ;  0 1 2     multiply those by 4 for the doubleword address of the matrix
  296. ;  3 4 5
  297. ;  6 7 8
  298. ;
  299. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  300.  
  301.            align 16
  302.  
  303. erotate:
  304.            mov eax,ematrix+8
  305.            imul ebp
  306.            shrd eax,edx,14
  307.            mov edi,eax
  308.            if usez eq yes
  309.            mov eax,ematrix+4
  310.            imul ecx
  311.            shrd eax,edx,14
  312.            add edi,eax
  313.            endif
  314.            mov eax,ematrix+0
  315.            imul ebx
  316.            shrd eax,edx,14
  317.            add edi,eax   ; di = new x
  318.  
  319.            mov eax,ematrix+20
  320.            imul ebp
  321.            shrd eax,edx,14
  322.            mov esi,eax
  323.            mov eax,ematrix+16
  324.            imul ecx
  325.            shrd eax,edx,14
  326.            add esi,eax
  327.            mov eax,ematrix+12
  328.            imul ebx
  329.            shrd eax,edx,14
  330.            add esi,eax   ; si = new y
  331.  
  332.            mov eax,ematrix+32
  333.            imul ebp
  334.            shrd eax,edx,14
  335.            mov ebp,eax
  336.            mov eax,ematrix+28
  337.            imul ecx
  338.            shrd eax,edx,14
  339.            add ebp,eax
  340.            mov eax,ematrix+24
  341.            imul ebx
  342.            shrd eax,edx,14
  343.            add ebp,eax   ; bp = new z
  344.  
  345.            mov ecx,esi
  346.            mov ebx,edi
  347.  
  348.            ret
  349.  
  350. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  351. ;
  352. ; Zsolve - 32 bit rotate point using ematrix - solve one variable only
  353. ; In:
  354. ;    EBX - x point
  355. ;    ECX - y point
  356. ;    EBP - z point
  357. ;    ematrix - 32 bit rotation matrix - set up by "setsincose" routine
  358. ;
  359. ; Out:
  360. ;    EBX - x point (same as entry)
  361. ;    ECX - y point (same as entry)
  362. ;    EBP - z point (same as entry)
  363. ;    ESI - new z point/location
  364. ;
  365. ; Notes:
  366. ;
  367. ; solve z from ematrix - same as above erotate but only solves z for fast
  368. ; test of where object is - result is in esi
  369. ;
  370. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  371.  
  372.            align 16
  373.  
  374. zsolve:
  375.            mov eax,ematrix+32
  376.            imul ebp
  377.            shrd eax,edx,14
  378.            mov esi,eax
  379.            mov eax,ematrix+28
  380.            imul ecx
  381.            shrd eax,edx,14
  382.            add esi,eax
  383.            mov eax,ematrix+24
  384.            imul ebx
  385.            shrd eax,edx,14
  386.            add esi,eax   ; si = new z
  387.            ret
  388.  
  389. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  390. ;
  391. ; Xsolve - 32 bit rotate point using ematrix - solve one variable only
  392. ; In:
  393. ;    EBX - x point
  394. ;    ECX - y point
  395. ;    EBP - z point
  396. ;    ematrix - 32 bit rotation matrix - set up by "setsincose" routine
  397. ;
  398. ; Out:
  399. ;    EBX - x point (same as entry)
  400. ;    ECX - y point (same as entry)
  401. ;    EBP - z point (same as entry)
  402. ;    EDI - new x point/location
  403. ;
  404. ; Notes:
  405. ; if object z test from above routine is positive, this routine will solve
  406. ; the rest of the rotation matrix.  this is so we don't waste time solving
  407. ; for x and y locations if the object is behind the camera anyway.
  408. ; saves imuls
  409. ;
  410. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  411.  
  412.            align 16
  413. xsolve:
  414.            mov eax,ematrix+8
  415.            imul ebp
  416.            shrd eax,edx,14
  417.            mov edi,eax
  418.            if usez eq yes
  419.            mov eax,ematrix+4
  420.            imul ecx
  421.            shrd eax,edx,14
  422.            add edi,eax
  423.            endif
  424.            mov eax,ematrix+0
  425.            imul ebx
  426.            shrd eax,edx,14
  427.            add edi,eax   ; di = new x
  428.            ret
  429.  
  430. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  431. ;
  432. ; Ysolve - 32 bit rotate point using ematrix - solve one variable only
  433. ; In:
  434. ;    EBX - x point
  435. ;    ECX - y point
  436. ;    EBP - z point
  437. ;    ESI - new z point
  438. ;    EDI - new x point
  439. ;    ematrix - 32 bit rotation matrix - set up by "setsincose" routine
  440. ;
  441. ; Out:
  442. ;    EBX - x new point from EDI
  443. ;    ECX - y new point
  444. ;    EBP - z new point from ESI
  445. ;
  446. ; Notes:
  447. ;
  448. ; solve y from ematrix - same as above xsolve but solves y for fast
  449. ; test of where object is.  final variables are then cleaned up to
  450. ; immitate the erotate function in parts.
  451. ;
  452. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  453.  
  454.            align 16
  455. ysolve:
  456.            mov eax,ematrix+16
  457.            imul ecx
  458.            shrd eax,edx,14
  459.            mov ecx,eax
  460.            mov eax,ematrix+12
  461.            imul ebx
  462.            shrd eax,edx,14
  463.            add ecx,eax
  464.            mov eax,ematrix+20
  465.            imul ebp
  466.            shrd eax,edx,14
  467.            add ecx,eax   ; cx = new y
  468.  
  469.            mov ebx,edi   ; final test, move into appropriate regs
  470.            mov ebp,esi
  471.  
  472.            ret
  473.  
  474. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  475. ;
  476. ;   Sign - 16 bit theta to 32bit sin(@)
  477. ; In:
  478. ;     AX - theta  0 - 65536 (0-360)
  479. ; Out:
  480. ;    EAX - sin (@)   (-4000h to 4000h)
  481. ;
  482. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  483. ;
  484. ; CoSign - 16 bit theta to 32bit cos(@)
  485. ; In:
  486. ;     AX - theta  0 - 65536 (0-360)
  487. ; Out:
  488. ;    EAX - cos (@)   (-4000h to 4000h)
  489. ;
  490. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  491. ;
  492. ; Notes:
  493. ; calculate sin into eax, from ax, smashes bx
  494. ; after imul by sin, shr eax,14 to compensate for decimal factor!
  495. ;  eg:
  496. ;    mov eax,sin(@)
  497. ;    mov ebx,32bitnumber
  498. ;    imul ebx
  499. ;    shrd eax,edx,14
  500. ;    eax = ebx*sin(@)
  501. ;
  502. ;    mov ax,sin(@)
  503. ;    mov bx,16bitnumber
  504. ;    imul bx
  505. ;    shrd ax,dx,14
  506. ;    eax = bx*sin(@)
  507. ;
  508. ; eax is simply a sign extended ax
  509. ;
  510. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  511.  
  512.            align 16
  513.  
  514. cosign:
  515.            add ax,4000h
  516. sign:
  517.            shr ax,2
  518.            cmp ax,2000h
  519.            jge s q3o4         ; quadrant 3 or 4
  520.  
  521.            cmp ax,1000h
  522.            jl s q0            ; quad 1
  523.  
  524.            mov ebx,1fffh
  525.            sub bx,ax
  526.            jmp s halfsign     ; quad 2
  527. q0:
  528.            movzx ebx,ax
  529.            jmp s halfsign
  530. q3o4:
  531.            cmp ax,3000h
  532.            jl s q3
  533.            mov ebx,3fffh
  534.            sub bx,ax
  535.            call halfsign      ; quad 4
  536.            neg eax
  537.            ret
  538. q3:
  539.            and ax,0fffh
  540.            movzx ebx,ax       ; quad 3
  541.            call halfsign
  542.            neg eax
  543.            ret
  544. halfsign:
  545.            xor eax,eax
  546.            mov ax,w sinus[ebx*2]
  547.            ret
  548.  
  549. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  550. ;
  551. ; Arctan - 32 bit rise/run to 16bit arctan(rise/run)
  552. ; In:
  553. ;    EAX - Run
  554. ;    ECX - Rise
  555. ; Out:
  556. ;     AX - arctan(ECX/EAX)
  557. ;
  558. ; Notes:
  559. ; smashes cx,ax,dx,si
  560. ; arctan(ecx/0) is valid and tested for
  561. ;
  562. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  563.  
  564.            align 16
  565.  
  566. arctan:
  567.            cmp eax,0
  568.            jl s qd2or3
  569.            cmp ecx,0
  570.            jge s halftax      ; quadrant 1
  571.            neg ecx            ; quadrant 4, ax=-ax
  572.            call halftan
  573.            neg ax
  574.            shl eax,2
  575.            ret
  576. qd2or3:
  577.            neg eax
  578.            cmp ecx,0
  579.            jge s qd2
  580.            neg ecx            ; quad 3, ax=ax+8192
  581.            call halftan
  582.            add ax,8192
  583.            shl eax,2
  584.            ret
  585. qd2:
  586.            call halftan
  587.            neg ax
  588.            add ax,8192
  589.            shl eax,2
  590.            ret
  591. halftax:
  592.            call halftan
  593.            shl eax,2
  594.            ret
  595.  
  596.            align 16
  597.  
  598. halftan:
  599.            xor edx,edx
  600.  
  601. ; cx=rise  positive
  602. ; ax=run   positive
  603.  
  604.            cmp eax,ecx
  605.            jl s opptan        ; greater than 45 degrees, other side...
  606.  
  607.            xchg ecx,eax       ; ax<cx
  608.            shld edx,eax,11    ; *2048 edx = high dword for divide
  609.            shl eax,11         ; *2048
  610.            div ecx
  611.            movzx esi,ax
  612.            mov ax,w negtan[esi*2] ; resulting angle (0-512 is 0-45) in ax
  613.            ret
  614.  
  615.            align 16
  616.  
  617. opptan:
  618.            shld edx,eax,11    ; *2048 edx = high dword for divide
  619.            shl eax,11         ; *2048
  620.  
  621.            div ecx
  622.            movzx esi,ax       ; ax remainder
  623.            mov cx,w negtan[esi*2]
  624.            mov eax,1000h
  625.            sub ax,cx          ; resulting angle (2048-4096 is 45-90) in ax
  626.            ret
  627.  
  628.            align 16
  629.  
  630. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  631. ;
  632. ; Compound - generate object matrix, 12 imul's first
  633. ; In:
  634. ;    ESI - Object # to get angles from
  635. ;    vxs[esi*2] - object x angle (0-65536)
  636. ;    vys[esi*2] - object y angle (0-65536)
  637. ;    vzs[esi*2] - object z angle (0-65536)
  638. ; Out:
  639. ;    vmatrix - resulting rotation matrix including camera matrix
  640. ;    ESI = ESI
  641. ;
  642. ; Notes:
  643. ;              x                         y                      z
  644. ;
  645. ;x=  cz * cy - sx * sy * sz   - sz * cy - sx * sy * cz     - cx * sy
  646. ;
  647. ;y=         sz * cx                   cx * cz                - sx
  648. ;
  649. ;z=  cz * sy + sx * sz * cy   - sy * sz + sx * cy * cz       cx * cy
  650. ;
  651. ;then perform matrix multiply by negative x and z matricies
  652. ;
  653. ; -x matrix                             -z matrix
  654. ;     x       y       z                   x       y       z
  655. ;
  656. ;x    1       0       0                cz     sz       0
  657. ;
  658. ;y    0      cx       sx              -sz     cz       0
  659. ;
  660. ;z    0     -sx       cx                0      0       1
  661. ;
  662. ; notice original object matrix takes 12 imuls, camera modify takes 24, can
  663. ; you do this faster? (less imuls)
  664. ;
  665. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  666.  
  667. compound:
  668.            push esi
  669.  
  670.            mov ax,vxs[esi*2]
  671.            neg ax
  672.            push eax
  673.            call cosign
  674.            mov vcosx,eax
  675.            pop eax
  676.            call sign
  677.            mov vsinx,eax
  678.            mov ebp,eax            ; bp = sx
  679.            neg eax
  680.            mov [vmatrix+20],eax
  681.  
  682.            mov ax,vzs[esi*2]
  683.            neg ax
  684.            push eax
  685.            call cosign
  686.            mov vcosz,eax
  687.            mov edi,eax            ; di = cz
  688.            pop eax
  689.            call sign
  690.            mov vsinz,eax
  691.            mov edx,eax            ; dx = sz
  692.  
  693.            mov ax,vys[esi*2]
  694.            neg ax
  695.            add ax,eyeay
  696.            push eax
  697.            call cosign
  698.            mov vcosy,eax
  699.            pop eax
  700.            call sign
  701.            mov vsiny,eax          ; ax = sy
  702.  
  703.            mov ebx,edx            ; save sz
  704.  
  705.            mov ecx,eax            ; save sy
  706.  
  707.            imul ebx               ; bx = - sy * sz
  708.            shr eax,14
  709.            movsx ebx,ax
  710.            neg ebx
  711.            mov [vmatrix+28],ebx
  712.  
  713.            mov eax,ecx            ; si = cz * sy
  714.            imul edi
  715.            shr eax,14
  716.            movsx esi,ax
  717.            mov [vmatrix+24],esi
  718.  
  719.            mov eax,vcosy
  720.  
  721.            imul edi               ; di = cy * cz
  722.            shr eax,14
  723.            movsx edi,ax
  724.            mov [vmatrix+0],edi
  725.  
  726.            mov eax,vsinz
  727.            mov ecx,vcosy
  728.  
  729.            imul ecx               ; cx = - sz * cy
  730.            shr eax,14
  731.            movsx ecx,ax
  732.            neg ecx
  733.            mov [vmatrix+4],ecx
  734.  
  735.            mov eax,ebp
  736.            imul esi
  737.            shr eax,14
  738.            movsx esi,ax
  739.            neg esi
  740.            add [vmatrix+4],esi
  741.  
  742.            mov eax,ebp
  743.            imul edi
  744.            shr eax,14
  745.            movsx edi,ax
  746.            add [vmatrix+28],edi
  747.  
  748.            mov eax,ebp
  749.            imul ebx
  750.            shr eax,14
  751.            movsx ebx,ax
  752.            add [vmatrix+0],ebx
  753.  
  754.            mov eax,ebp
  755.            imul ecx
  756.            shr eax,14
  757.            movsx ecx,ax
  758.            neg ecx
  759.            add [vmatrix+24],ecx
  760.  
  761.            mov esi,vcosx
  762.  
  763.            mov eax,vcosy
  764.            imul esi                   ; cx * cy
  765.            shr eax,14
  766.            movsx eax,ax
  767.            mov [vmatrix+32],eax
  768.  
  769.            mov eax,vsiny
  770.            imul esi                   ;-cx * sy
  771.            shr eax,14
  772.            movsx eax,ax
  773.            neg eax
  774.            mov [vmatrix+8],eax
  775.  
  776.            mov eax,vsinz
  777.            imul esi                   ; cx * sz
  778.            shr eax,14
  779.            movsx eax,ax
  780.            mov [vmatrix+12],eax
  781.  
  782.            mov eax,vcosz
  783.            imul esi                   ; cx * cz
  784.            shr eax,14
  785.            movsx eax,ax
  786.            mov [vmatrix+16],eax
  787.  
  788.            mov edi,ecosx              ; now perform camera x rotation,12 imuls
  789.            mov esi,esinx
  790.            mov ebp,esi
  791.            neg ebp
  792.  
  793.            mov eax,[vmatrix+12]
  794.            imul edi
  795.            shr eax,14
  796.            movsx ecx,ax
  797.  
  798.            mov eax,[vmatrix+24]
  799.            imul esi
  800.            shr eax,14
  801.            movsx eax,ax
  802.  
  803.            add ecx,eax                ; ecx = new vmatrix+12
  804.  
  805.            mov eax,[vmatrix+12]
  806.            imul ebp
  807.            shr eax,14
  808.            movsx ebx,ax
  809.  
  810.            mov eax,[vmatrix+24]
  811.            imul edi
  812.            shr eax,14
  813.            movsx eax,ax
  814.  
  815.            add ebx,eax                ; ebx = new vmatrix+24
  816.  
  817.            mov [vmatrix+12],ecx
  818.            mov [vmatrix+24],ebx
  819.  
  820.            mov eax,[vmatrix+16]
  821.            imul edi
  822.            shr eax,14
  823.            movsx ecx,ax
  824.  
  825.            mov eax,[vmatrix+28]
  826.            imul esi
  827.            shr eax,14
  828.            movsx eax,ax
  829.  
  830.            add ecx,eax                ; ecx = new vmatrix+16
  831.  
  832.            mov eax,[vmatrix+16]
  833.            imul ebp
  834.            shr eax,14
  835.            movsx ebx,ax
  836.  
  837.            mov eax,[vmatrix+28]
  838.            imul edi
  839.            shr eax,14
  840.            movsx eax,ax
  841.  
  842.            add ebx,eax                ; ebx = new vmatrix+28
  843.  
  844.            mov [vmatrix+16],ecx
  845.            mov [vmatrix+28],ebx
  846.  
  847.            mov eax,[vmatrix+20]
  848.            imul edi
  849.            shr eax,14
  850.            movsx ecx,ax
  851.  
  852.            mov eax,[vmatrix+32]
  853.            imul esi
  854.            shr eax,14
  855.            movsx eax,ax
  856.  
  857.            add ecx,eax                ; ecx = new vmatrix+20
  858.  
  859.            mov eax,[vmatrix+20]
  860.            imul ebp
  861.            shr eax,14
  862.            movsx ebx,ax
  863.  
  864.            mov eax,[vmatrix+32]
  865.            imul edi
  866.            shr eax,14
  867.            movsx eax,ax
  868.  
  869.            add ebx,eax                ; ebx = new vmatrix+32
  870.  
  871.            mov [vmatrix+20],ecx
  872.            mov [vmatrix+32],ebx
  873.  
  874.            if usez eq yes
  875.  
  876.            mov edi,ecosz              ; now perform camera z rotation,12 imuls
  877.            mov esi,esinz
  878.            mov ebp,esi
  879.            neg esi
  880.  
  881.            mov eax,[vmatrix+0]
  882.            imul edi
  883.            shr eax,14
  884.            movsx ecx,ax
  885.  
  886.            mov eax,[vmatrix+12]
  887.            imul esi
  888.            shr eax,14
  889.            movsx eax,ax
  890.  
  891.            add ecx,eax
  892.  
  893.            mov eax,[vmatrix+0]
  894.            imul ebp
  895.            shr eax,14
  896.            movsx ebx,ax
  897.  
  898.            mov eax,[vmatrix+12]
  899.            imul edi
  900.            shr eax,14
  901.            movsx eax,ax
  902.  
  903.            add ebx,eax
  904.  
  905.            mov [vmatrix+0],ecx
  906.            mov [vmatrix+12],ebx
  907.  
  908.            mov eax,[vmatrix+4]
  909.            imul edi
  910.            shr eax,14
  911.            movsx ecx,ax
  912.  
  913.            mov eax,[vmatrix+16]
  914.            imul esi
  915.            shr eax,14
  916.            movsx eax,ax
  917.  
  918.            add ecx,eax
  919.  
  920.            mov eax,[vmatrix+4]
  921.            imul ebp
  922.            shr eax,14
  923.            movsx ebx,ax
  924.  
  925.            mov eax,[vmatrix+16]
  926.            imul edi
  927.            shr eax,14
  928.            movsx eax,ax
  929.  
  930.            add ebx,eax
  931.  
  932.            mov [vmatrix+4],ecx
  933.            mov [vmatrix+16],ebx
  934.  
  935.            mov eax,[vmatrix+8]
  936.            imul edi
  937.            shr eax,14
  938.            movsx ecx,ax
  939.  
  940.            mov eax,[vmatrix+20]
  941.            imul esi
  942.            shr eax,14
  943.            movsx eax,ax
  944.  
  945.            add ecx,eax
  946.  
  947.            mov eax,[vmatrix+8]
  948.            imul ebp
  949.            shr eax,14
  950.            movsx ebx,ax
  951.  
  952.            mov eax,[vmatrix+20]
  953.            imul edi
  954.            shr eax,14
  955.            movsx eax,ax
  956.  
  957.            add ebx,eax
  958.  
  959.            mov [vmatrix+8],ecx
  960.            mov [vmatrix+20],ebx
  961.  
  962.            endif
  963.  
  964.            pop esi
  965.            ret
  966.  
  967. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  968. ;
  969. ; Setsincose - generate rotation matrix for  y,x,z  camera rotation
  970. ;
  971. ; In:
  972. ;    eyeax - camera x angle (0-65536)
  973. ;    eyeay - camera y angle (0-65536)
  974. ;    eyeaz - camera z angle (0-65536)
  975. ; Out:
  976. ;    vmatrix - resulting rotation matrix including camera matrix
  977. ;
  978. ; Notes:
  979. ; called only once every frame.  completed in 12 multiplys
  980. ; matrix is also used for objects with no rotation (always angle 0,0,0)
  981. ;
  982. ; where is my postcard! see readme.doc for info.
  983. ;
  984. ;              x                    y                    z
  985. ;
  986. ; x=  cz * cy + sx * sy * sz     -cx * sz     - sy * cz + sx * cy * sz
  987. ;
  988. ; y=  sz * cy - sx * sy * cz      cx * cz     - sy * sz - sz * cy * cz
  989. ;
  990. ; z=         cx * sy                 sx                cx * cy
  991. ;
  992. ;
  993. ;  matrix offsets: (doublewords)
  994. ;
  995. ;     x  y  z
  996. ;
  997. ; x    0  4  8
  998. ; y   12 16 20
  999. ; z   24 28 32
  1000. ;
  1001. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1002.  
  1003.            align 16
  1004.  
  1005. setsincose:
  1006.  
  1007.            mov ax,eyeax
  1008.            call cosign
  1009.            mov ecosx,eax          ; ecosx and such are used by object rotation
  1010.            mov ax,eyeax           ; ematrix is used to find where object is
  1011.            call sign
  1012.            mov esinx,eax
  1013.            mov [ematrix+28],eax
  1014.            mov ebp,eax            ; bp = sx
  1015.  
  1016.            if usez eq yes
  1017.            mov ax,eyeaz
  1018.            call cosign
  1019.            mov ecosz,eax
  1020.            mov edi,eax            ; di = cz
  1021.            mov ax,eyeaz
  1022.            call sign
  1023.            mov esinz,eax
  1024.            mov edx,eax            ; dx = sz
  1025.            endif
  1026.  
  1027.            if usez eq no
  1028.            mov edi,4000h          ; di = cos 0
  1029.            mov ecosz,4000h
  1030.            xor edx,edx            ; dx = sin 0
  1031.            mov esinz,0
  1032.            endif
  1033.  
  1034.            mov ax,eyeay
  1035.            call cosign
  1036.            mov ecosy,eax
  1037.            mov ax,eyeay
  1038.            call sign
  1039.            mov esiny,eax          ; ax = sy
  1040.  
  1041.            mov ebx,edx            ; save sz
  1042.  
  1043.            mov ecx,eax            ; save sy
  1044.  
  1045.            imul bx                ; bx = sy * sz
  1046.            shrd ax,dx,14
  1047.            movsx ebx,ax
  1048.            neg ebx
  1049.            mov [ematrix+20],ebx
  1050.            neg ebx
  1051.  
  1052.            mov eax,ecx            ; si = - (cz * sy)
  1053.            imul di
  1054.            shrd ax,dx,14
  1055.            movsx esi,ax
  1056.            neg esi
  1057.            mov [ematrix+8],esi
  1058.  
  1059.            mov eax,ecosy
  1060.  
  1061.            imul di                ; di = cy * cz
  1062.            shrd ax,dx,14
  1063.            movsx edi,ax
  1064.            mov [ematrix+0],edi
  1065.  
  1066.            mov eax,esinz
  1067.            mov ecx,ecosy
  1068.  
  1069.            imul cx                ; cx = sz * cy
  1070.            shrd ax,dx,14
  1071.            movsx ecx,ax
  1072.            mov [ematrix+12],ecx
  1073.  
  1074.            mov eax,ebp
  1075.            imul si
  1076.            shrd ax,dx,14
  1077.            movsx esi,ax
  1078.            add [ematrix+12],esi
  1079.  
  1080.            mov eax,ebp
  1081.            imul di
  1082.            shrd ax,dx,14
  1083.            movsx edi,ax
  1084.            neg edi
  1085.            add [ematrix+20],edi
  1086.  
  1087.            mov eax,ebp
  1088.            imul bx
  1089.            shrd ax,dx,14
  1090.            movsx ebx,ax
  1091.            add [ematrix+0],ebx
  1092.  
  1093.            mov eax,ebp
  1094.            imul cx
  1095.            shrd ax,dx,14
  1096.            movsx ecx,ax
  1097.            add [ematrix+8],ecx
  1098.  
  1099.            mov esi,ecosx
  1100.  
  1101.            mov eax,ecosy
  1102.            imul si                    ; cx * cy
  1103.            shrd ax,dx,14
  1104.            movsx eax,ax
  1105.            mov [ematrix+32],eax
  1106.  
  1107.            mov eax,esiny
  1108.            imul si                    ; cx * sy
  1109.            shrd ax,dx,14
  1110.            movsx eax,ax
  1111.            mov [ematrix+24],eax
  1112.  
  1113.            mov eax,esinz
  1114.            imul si                    ;-cx * sz
  1115.            shrd ax,dx,14
  1116.            movsx eax,ax
  1117.            neg eax
  1118.            mov [ematrix+4],eax
  1119.  
  1120.            mov eax,ecosz
  1121.            imul si                    ; cx * cz
  1122.            shrd ax,dx,14
  1123.            movsx eax,ax
  1124.            mov [ematrix+16],eax
  1125.  
  1126.            neg esinx                  ; reverse angles for object rotation
  1127.            neg esiny
  1128.  
  1129.            ret
  1130.  
  1131. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1132. ;
  1133. ; Temp_Matrix: generate temp matrix, 12 imul's, from object esi
  1134. ;
  1135. ; In:
  1136. ;    ESI - Object # to get angles from
  1137. ;    vxs[esi*2] - object x angle (0-65536)
  1138. ;    vys[esi*2] - object y angle (0-65536)
  1139. ;    vzs[esi*2] - object z angle (0-65536)
  1140. ; Out:
  1141. ;    tmatrix - resulting rotation matrix (excluding camera matrix)
  1142. ;    ESI = ESI
  1143. ;
  1144. ; Notes:
  1145. ;              x                         y                      z
  1146. ;
  1147. ;x=  cz * cy - sx * sy * sz   - sz * cy - sx * sy * cz     - cx * sy
  1148. ;
  1149. ;y=         sz * cx                   cx * cz                - sx
  1150. ;
  1151. ;z=  cz * sy + sx * sz * cy   - sy * sz + sx * cy * cz       cx * cy
  1152. ;
  1153. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1154.  
  1155. temp_matrix:
  1156.            push esi
  1157.  
  1158.            mov ax,vxs[esi*2]
  1159.            neg ax
  1160.            push eax
  1161.            call cosign
  1162.            mov vcosx,eax
  1163.            pop eax
  1164.            call sign
  1165.            mov vsinx,eax
  1166.            mov ebp,eax            ; bp = sx
  1167.            neg eax
  1168.            mov [tmatrix+20],eax
  1169.  
  1170.            mov ax,vzs[esi*2]
  1171.            neg ax
  1172.            push eax
  1173.            call cosign
  1174.            mov vcosz,eax
  1175.            mov edi,eax            ; di = cz
  1176.            pop eax
  1177.            call sign
  1178.            mov vsinz,eax
  1179.            mov edx,eax            ; dx = sz
  1180.  
  1181.            mov ax,vys[esi*2]
  1182.            neg ax
  1183.            push eax
  1184.            call cosign
  1185.            mov vcosy,eax
  1186.            pop eax
  1187.            call sign
  1188.            mov vsiny,eax          ; ax = sy
  1189.  
  1190.            mov ebx,edx            ; save sz
  1191.  
  1192.            mov ecx,eax            ; save sy
  1193.  
  1194.            imul ebx               ; bx = - sy * sz
  1195.            shr eax,14
  1196.            movsx ebx,ax
  1197.            neg ebx
  1198.            mov [tmatrix+28],ebx
  1199.  
  1200.            mov eax,ecx            ; si = cz * sy
  1201.            imul edi
  1202.            shr eax,14
  1203.            movsx esi,ax
  1204.            mov [tmatrix+24],esi
  1205.  
  1206.            mov eax,vcosy
  1207.  
  1208.            imul edi               ; di = cy * cz
  1209.            shr eax,14
  1210.            movsx edi,ax
  1211.            mov [tmatrix+0],edi
  1212.  
  1213.            mov eax,vsinz
  1214.            mov ecx,vcosy
  1215.  
  1216.            imul ecx               ; cx = - sz * cy
  1217.            shr eax,14
  1218.            movsx ecx,ax
  1219.            neg ecx
  1220.            mov [tmatrix+4],ecx
  1221.  
  1222.            mov eax,ebp
  1223.            imul esi
  1224.            shr eax,14
  1225.            movsx esi,ax
  1226.            neg esi
  1227.            add [tmatrix+4],esi
  1228.  
  1229.            mov eax,ebp
  1230.            imul edi
  1231.            shr eax,14
  1232.            movsx edi,ax
  1233.            add [tmatrix+28],edi
  1234.  
  1235.            mov eax,ebp
  1236.            imul ebx
  1237.            shr eax,14
  1238.            movsx ebx,ax
  1239.            add [tmatrix+0],ebx
  1240.  
  1241.            mov eax,ebp
  1242.            imul ecx
  1243.            shr eax,14
  1244.            movsx ecx,ax
  1245.            neg ecx
  1246.            add [tmatrix+24],ecx
  1247.  
  1248.            mov esi,vcosx
  1249.  
  1250.            mov eax,vcosy
  1251.            imul esi                   ; cx * cy
  1252.            shr eax,14
  1253.            movsx eax,ax
  1254.            mov [tmatrix+32],eax
  1255.  
  1256.            mov eax,vsiny
  1257.            imul esi                   ;-cx * sy
  1258.            shr eax,14
  1259.            movsx eax,ax
  1260.            neg eax
  1261.            mov [tmatrix+8],eax
  1262.  
  1263.            mov eax,vsinz
  1264.            imul esi                   ; cx * sz
  1265.            shr eax,14
  1266.            movsx eax,ax
  1267.            mov [tmatrix+12],eax
  1268.  
  1269.            mov eax,vcosz
  1270.            imul esi                   ; cx * cz
  1271.            shr eax,14
  1272.            movsx eax,ax
  1273.            mov [tmatrix+16],eax
  1274.  
  1275.            pop esi
  1276.            ret
  1277.  
  1278. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1279. ;
  1280. ; Temp_Rotate - 32 bit rotate point using tmatrix
  1281. ; In:
  1282. ;    EBX - x point
  1283. ;    ECX - y point
  1284. ;    EBP - z point
  1285. ;     tmatrix - 32 bit rotation matrix - set up by "temp_matrix" routine
  1286. ; Out:
  1287. ;    EBX - x point
  1288. ;    ECX - y point
  1289. ;    EBP - z point
  1290. ;
  1291. ; Notes:
  1292. ;  Same as rotate and erotate
  1293. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1294.  
  1295. temp_rotate:
  1296.            mov eax,tmatrix+8    ; solve x = bx(0)+cx(1)+bp(2)
  1297.            imul ebp
  1298.            shrd eax,edx,14
  1299.            mov edi,eax
  1300.            mov eax,tmatrix+4
  1301.            imul ecx
  1302.            shrd eax,edx,14
  1303.            add edi,eax
  1304.            mov eax,tmatrix+0
  1305.            imul ebx
  1306.            shrd eax,edx,14
  1307.            add edi,eax   ; di = new x
  1308.  
  1309.            mov eax,tmatrix+20   ; solve y = bx(3)+cx(4)+bp(5)
  1310.            imul ebp
  1311.            shrd eax,edx,14
  1312.            mov esi,eax
  1313.            mov eax,tmatrix+16
  1314.            imul ecx
  1315.            shrd eax,edx,14
  1316.            add esi,eax
  1317.            mov eax,tmatrix+12
  1318.            imul ebx
  1319.            shrd eax,edx,14
  1320.            add esi,eax   ; si = new y
  1321.  
  1322.            mov eax,tmatrix+32   ; solve z = bx(6)+cx(7)+bp(8)
  1323.            imul ebp
  1324.            shrd eax,edx,14
  1325.            mov ebp,eax
  1326.            mov eax,tmatrix+28
  1327.            imul ecx
  1328.            shrd eax,edx,14
  1329.            add ebp,eax
  1330.            mov eax,tmatrix+24
  1331.            imul ebx
  1332.            shrd eax,edx,14
  1333.            add ebp,eax   ; bp = new z
  1334.  
  1335.            mov ecx,esi
  1336.            mov ebx,edi
  1337.  
  1338.            ret
  1339.  
  1340. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1341. ;
  1342. ; Matrix_Multiply: multiply tmatrix by vmatrix, [vmatrix]=[tmatrix][vmatrix]
  1343. ;
  1344. ; In:
  1345. ;    vmatrix - rotation matrix
  1346. ;    tmatrix - rotation matrix
  1347. ; Out:
  1348. ;    vmatrix - resulting rotation matrix
  1349. ;
  1350. ; Notes:
  1351. ;
  1352. ; [ tmatrix+ 0 tmatrix+ 2 tmatrix+ 4 ] [ vmatrix+ 0 vmatrix+ 2 vmatrix+ 4 ]
  1353. ; [                                  ] [                                  ]
  1354. ; [ tmatrix+ 6 tmatrix+ 8 tmatrix+10 ] [ vmatrix+ 6 vmatrix+ 8 vmatrix+10 ]
  1355. ; [                                  ] [                                  ]
  1356. ; [ tmatrix+12 tmatrix+14 tmatrix+16 ] [ vmatrix+12 vmatrix+14 vmatrix+16 ]
  1357. ;
  1358. ; Think of it this way, this routine will generate a resulting matrix as  if
  1359. ; you rotated an  object by tmatrix, then rotated  the  object  by  vmatrix.
  1360. ; Instead, call this routine then you will only have to rotate the object by
  1361. ; Vmatrix!.
  1362. ;
  1363. ; Notice Tmatrix is done before Vmatrix!!  This is used for calculating the
  1364. ; positions of arms on bodies, hands on arms, fingers on hands...etc...
  1365. ;
  1366. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1367.  
  1368. matrix_multiply:
  1369.  
  1370.            mov ebx,[vmatrix+0]
  1371.            mov ecx,[vmatrix+4]
  1372.            mov ebp,[vmatrix+8]
  1373.  
  1374.            mov eax,[tmatrix+0]
  1375.            imul ebx
  1376.            shrd eax,edx,14
  1377.            mov esi,eax
  1378.  
  1379.            mov eax,[tmatrix+12]
  1380.            imul ecx
  1381.            shrd eax,edx,14
  1382.            add esi,eax
  1383.  
  1384.            mov eax,[tmatrix+24]
  1385.            imul ebp
  1386.            shrd eax,edx,14
  1387.            add esi,eax
  1388.  
  1389.            push esi             ; tmatrix+0
  1390.  
  1391.            mov eax,[tmatrix+4]
  1392.            imul ebx
  1393.            shrd eax,edx,14
  1394.            mov esi,eax
  1395.  
  1396.            mov eax,[tmatrix+16]
  1397.            imul ecx
  1398.            shrd eax,edx,14
  1399.            add esi,eax
  1400.  
  1401.            mov eax,[tmatrix+28]
  1402.            imul ebp
  1403.            shrd eax,edx,14
  1404.            add esi,eax
  1405.  
  1406.            push esi             ; tmatrix+4
  1407.  
  1408.            mov eax,[tmatrix+8]
  1409.            imul ebx
  1410.            shrd eax,edx,14
  1411.            mov esi,eax
  1412.  
  1413.            mov eax,[tmatrix+20]
  1414.            imul ecx
  1415.            shrd eax,edx,14
  1416.            add esi,eax
  1417.  
  1418.            mov eax,[tmatrix+32]
  1419.            imul ebp
  1420.            shrd eax,edx,14
  1421.            add esi,eax
  1422.  
  1423.            push esi             ; tmatrix+8
  1424.  
  1425.            mov ebx,[vmatrix+12]
  1426.            mov ecx,[vmatrix+16]
  1427.            mov ebp,[vmatrix+20]
  1428.  
  1429.            mov eax,[tmatrix+0]
  1430.            imul ebx
  1431.            shrd eax,edx,14
  1432.            mov esi,eax
  1433.  
  1434.            mov eax,[tmatrix+12]
  1435.            imul ecx
  1436.            shrd eax,edx,14
  1437.            add esi,eax
  1438.  
  1439.            mov eax,[tmatrix+24]
  1440.            imul ebp
  1441.            shrd eax,edx,14
  1442.            add esi,eax
  1443.  
  1444.            push esi             ; tmatrix+12
  1445.  
  1446.            mov eax,[tmatrix+4]
  1447.            imul ebx
  1448.            shrd eax,edx,14
  1449.            mov esi,eax
  1450.  
  1451.            mov eax,[tmatrix+16]
  1452.            imul ecx
  1453.            shrd eax,edx,14
  1454.            add esi,eax
  1455.  
  1456.            mov eax,[tmatrix+28]
  1457.            imul ebp
  1458.            shrd eax,edx,14
  1459.            add esi,eax
  1460.  
  1461.            push esi             ; tmatrix+16
  1462.  
  1463.            mov eax,[tmatrix+8]
  1464.            imul ebx
  1465.            shrd eax,edx,14
  1466.            mov esi,eax
  1467.  
  1468.            mov eax,[tmatrix+20]
  1469.            imul ecx
  1470.            shrd eax,edx,14
  1471.            add esi,eax
  1472.  
  1473.            mov eax,[tmatrix+32]
  1474.            imul ebp
  1475.            shrd eax,edx,14
  1476.            add esi,eax
  1477.  
  1478.            push esi             ; tmatrix+20
  1479.  
  1480.            mov ebx,[vmatrix+24]
  1481.            mov ecx,[vmatrix+28]
  1482.            mov ebp,[vmatrix+32]
  1483.  
  1484.            mov eax,[tmatrix+0]
  1485.            imul ebx
  1486.            shrd eax,edx,14
  1487.            mov esi,eax
  1488.  
  1489.            mov eax,[tmatrix+12]
  1490.            imul ecx
  1491.            shrd eax,edx,14
  1492.            add esi,eax
  1493.  
  1494.            mov eax,[tmatrix+24]
  1495.            imul ebp
  1496.            shrd eax,edx,14
  1497.            add esi,eax
  1498.  
  1499.            push esi             ; tmatrix+24
  1500.  
  1501.            mov eax,[tmatrix+4]
  1502.            imul ebx
  1503.            shrd eax,edx,14
  1504.            mov esi,eax
  1505.  
  1506.            mov eax,[tmatrix+16]
  1507.            imul ecx
  1508.            shrd eax,edx,14
  1509.            add esi,eax
  1510.  
  1511.            mov eax,[tmatrix+28]
  1512.            imul ebp
  1513.            shrd eax,edx,14
  1514.            add esi,eax
  1515.  
  1516.            push esi             ; tmatrix+28
  1517.  
  1518.            mov eax,[tmatrix+8]
  1519.            imul ebx
  1520.            shrd eax,edx,14
  1521.            mov esi,eax
  1522.  
  1523.            mov eax,[tmatrix+20]
  1524.            imul ecx
  1525.            shrd eax,edx,14
  1526.            add esi,eax
  1527.  
  1528.            mov eax,[tmatrix+32]
  1529.            imul ebp
  1530.            shrd eax,edx,14
  1531.            add esi,eax
  1532.  
  1533. ;          push esi             ; tmatrix+32
  1534.  
  1535. ;          pop esi
  1536.            mov [vmatrix+32],esi
  1537.            pop esi
  1538.            mov [vmatrix+28],esi
  1539.            pop esi
  1540.            mov [vmatrix+24],esi
  1541.            pop esi
  1542.            mov [vmatrix+20],esi
  1543.            pop esi
  1544.            mov [vmatrix+16],esi
  1545.            pop esi
  1546.            mov [vmatrix+12],esi
  1547.            pop esi
  1548.            mov [vmatrix+ 8],esi
  1549.            pop esi
  1550.            mov [vmatrix+ 4],esi
  1551.            pop esi
  1552.            mov [vmatrix+ 0],esi
  1553.            ret
  1554.  
  1555. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1556. ;
  1557. ; Getroot:  ax = sqr(ax)
  1558. ;
  1559. ; In:
  1560. ;    AX - number to take square root of (0 - 65535)
  1561. ; Out:
  1562. ;    AX - Square root
  1563. ;
  1564. ; Notes:
  1565. ; I like TRANs method better - greater resolution and it doesn't require the
  1566. ; table. Im not too sure whos method is faster.
  1567. ;
  1568. ; This routine is not used in the main animation loop.  It could be used for
  1569. ; things like determining collision detection since collision does not require
  1570. ; much accuracy and collision does require many many checks.
  1571. ;
  1572. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1573. ;
  1574. ;           include squares.inc
  1575. ;
  1576. ;getroot:                      ; get square root of ax, where ax = 0-65535
  1577. ;           cmp ax,0fe01h      ; since ax cannot be negative anyway!
  1578. ;           jae sqr255         ; routine requires squares tables.
  1579. ;           mov si,offset squares
  1580. ;           mov cx,ax
  1581. ;           inc cx
  1582. ;           cld
  1583. ;nextroot:
  1584. ;           lodsw
  1585. ;           cmp ax,cx
  1586. ;           jbe  nextroot      ; jb is exact but jbe is better approximation
  1587. ;           mov ax,si
  1588. ;           sub ax,offset squares+3
  1589. ;           sar ax,1
  1590. ;           ret
  1591. ;sqr255:
  1592. ;           mov ax,255
  1593. ;           ret
  1594.  
  1595. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1596. ;
  1597. ; _Squareroot32:  ax = sqr(ax)
  1598. ; In:
  1599. ;   EAX - number to take square root of (32bit)
  1600. ; Out:
  1601. ;   EAX = EBX = Square root
  1602. ; Notes:
  1603. ;  This came from Dave Stamp's VR386 - Hey, he's short, fat, and stupid looking
  1604. ;  but I liked his routine anyway...
  1605. ;
  1606. ;  takes root of 32 bit number to 16 bit result
  1607. ;  about 220 clocks worst case:
  1608. ;  3 us on 486/66 and 10 us on 386/25
  1609. ;
  1610. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1611.  
  1612. sqrt32  macro
  1613.         local skip
  1614.         shld edx,eax,2 ; get 2 bits of input to error
  1615.         shl eax,2
  1616.         add ebx,ebx    ; estimate*2
  1617.         mov ecx,ebx    ; temp = est*2
  1618.         add ecx,ecx
  1619.         cmp edx,ecx    ; error>2*est?
  1620.         jle s skip
  1621.         inc ebx        ; yes, update for new bit added
  1622.         inc ecx
  1623.         sub edx,ecx
  1624. skip:
  1625.         endm
  1626.  
  1627.         public _squareroot32
  1628.  
  1629. _squareroot32:
  1630.         test eax,0ffff0000h  ; can we cut it in half?
  1631.         jne s hasupper
  1632.  
  1633.         shl eax,16           ; yes, so prescale
  1634.         test eax,0ff000000h  ; half again?
  1635.         jne do16
  1636.  
  1637.         shl eax,8            ; yes, prescale
  1638.         jmp do8              ; do 8 loops
  1639.  
  1640. hasupper:
  1641.         test eax,0ff000000h  ; half again?
  1642.         jne do32
  1643.         shl eax,8
  1644.         jmp do24
  1645. do32:
  1646.         sqrt32
  1647.         sqrt32
  1648.         sqrt32
  1649.         sqrt32
  1650. do24:
  1651.         sqrt32
  1652.         sqrt32
  1653.         sqrt32
  1654.         sqrt32
  1655. do16:
  1656.         sqrt32
  1657.         sqrt32
  1658.         sqrt32
  1659.         sqrt32
  1660. do8:
  1661.         sqrt32
  1662.         sqrt32
  1663.         sqrt32
  1664.         sqrt32
  1665.  
  1666.         mov eax,ebx        ; result in eax and ebx
  1667.         ret
  1668.  
  1669. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1670. ;
  1671. ; Sqrt: Routine courtesy TRAN
  1672. ;
  1673. ; In:
  1674. ;   EAX - number to take root of
  1675. ; Out:
  1676. ;   EAX - root
  1677. ;
  1678. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1679. sqrtbasetbl db 0,1,4,9,16,25,36,49,64,81,100,121,144,169,196,225
  1680.  
  1681.            public sqrt
  1682.  
  1683.            align 16
  1684.  
  1685. sqrt:
  1686.            pushad
  1687.            mov ebp,eax
  1688.            bsr ebx,eax
  1689.            jnz short sqrtf0
  1690.            xor ebx,ebx
  1691. sqrtf0:
  1692.            shr ebx,3
  1693.            lea eax,[ebx*8]
  1694.            mov cl,32
  1695.            sub cl,al
  1696.            rol ebp,cl
  1697.            mov eax,ebp
  1698.            movzx eax,al
  1699.            mov edi,offset sqrtbasetbl
  1700.            mov ecx,10h
  1701. sqrtl0:
  1702.            scasb
  1703.            je short sqrtl0d
  1704.            jb short sqrtl0d2
  1705.            loop sqrtl0
  1706.            inc edi
  1707. sqrtl0d2:
  1708.            dec edi
  1709.            inc cl
  1710. sqrtl0d:
  1711.            movzx edx,byte ptr [edi-1]
  1712.            dec cl
  1713.            xor cl,0fh
  1714.            mov edi,ecx
  1715.            mov ecx,ebx
  1716.            jecxz short sqrtdone
  1717.            sub eax,edx
  1718. sqrtml:
  1719.            shld eax,ebp,8
  1720.            rol ebp,8
  1721.            mov ebx,edi
  1722.            shl ebx,5
  1723.            xor edx,edx
  1724.            mov esi,eax
  1725.            div ebx
  1726.            rol edi,4
  1727.            add edi,eax
  1728.            add ebx,eax
  1729. sqrtf2:
  1730.            imul eax,ebx
  1731.            mov edx,eax
  1732.            mov eax,esi
  1733.            sub eax,edx
  1734.            jc short sqrtf1
  1735.            loop sqrtml
  1736. sqrtdone:
  1737.            mov [esp+28],edi
  1738.            popad
  1739.            ret
  1740. sqrtf1:
  1741.            dec ebx
  1742.            dec edi
  1743.            movzx eax,bl
  1744.            and al,1fh
  1745.            jmp sqrtf2
  1746.  
  1747. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1748. ;
  1749. ; Set_precal147: Set precal7 for plane transformation
  1750. ;
  1751. ; In:
  1752. ;   ECX - y location to pre-calculate plane to
  1753. ; Out:
  1754. ;   precal1
  1755. ;   precal4
  1756. ;   precal7
  1757. ;
  1758. ; Notes:
  1759. ; Plane is ecx and allows above formulas to determine where a
  1760. ; point/object would be along that plane if z is not negative
  1761. ;
  1762. ; Good for runway translations or super huge background polygons - not used
  1763. ; by regular 3d.asm routines
  1764. ;
  1765. ; How to use: lets say you've got a billion background objects that are
  1766. ; on the ground (or all on the same y plane).  you call set_precal147
  1767. ; with that y plane location and use frotate instead of erotate to
  1768. ; determine where points rotated along that plane will end up.  this
  1769. ; speeds the routine up by 33% by cutting out 3 imuls.
  1770. ;
  1771. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1772.  
  1773.             align 16
  1774.  
  1775. precal1     dd 0
  1776. precal4     dd 0
  1777. precal7     dd 0
  1778.  
  1779. set_precal147:
  1780.             if usez eq yes
  1781.             mov eax,ecx
  1782.             sub eax,eyey
  1783.             imul ematrix+4
  1784.             shrd eax,edx,14
  1785.             mov precal1,eax
  1786.             endif
  1787.  
  1788.             mov eax,ecx
  1789.             sub eax,eyey
  1790.             imul ematrix+16
  1791.             shrd eax,edx,14
  1792.             mov precal4,eax
  1793.  
  1794. set_precal7:
  1795.             sub ecx,eyey
  1796.             mov eax,ecx
  1797.             imul ematrix+28
  1798.             shrd eax,edx,14
  1799.             mov precal7,eax
  1800.             ret
  1801.  
  1802.             align 16
  1803.  
  1804. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1805. ;
  1806. ; Frotate: fast object/point rotation along pre-calculated y plane
  1807. ;
  1808. ; In:
  1809. ;    EBX - x point
  1810. ;    ECX - y point
  1811. ;    EBP - z point
  1812. ;    ematrix - 32 bit rotation matrix - set up by "setsincose" routine
  1813. ;    precal1 - set up by set_precal147
  1814. ;    precal4 - set up by set_precal147
  1815. ;    precal7 - set up by set_precal147
  1816. ;
  1817. ; Out:
  1818. ;    EBX - x point
  1819. ;    ECX - y point
  1820. ;    EBP - z point
  1821. ;
  1822. ; Notes:
  1823. ;    see above
  1824. ;
  1825. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1826.  
  1827. frotate:
  1828.            mov eax,ematrix+8
  1829.            imul ebp
  1830.            shrd eax,edx,14
  1831.            mov edi,eax
  1832.            if usez eq yes
  1833.            add edi,precal1
  1834.            endif
  1835.            mov eax,ematrix+0
  1836.            imul ebx
  1837.            shrd eax,edx,14
  1838.            add edi,eax   ; di = new x
  1839.  
  1840.            mov eax,ematrix+20
  1841.            imul ebp
  1842.            shrd eax,edx,14
  1843.            mov esi,eax
  1844.            add esi,precal4
  1845.            mov eax,ematrix+12
  1846.            imul ebx
  1847.            shrd eax,edx,14
  1848.            add esi,eax   ; si = new y
  1849.  
  1850.            mov eax,ematrix+32
  1851.            imul ebp
  1852.            shrd eax,edx,14
  1853.            mov ebp,eax
  1854.            add ebp,precal7
  1855.            mov eax,ematrix+24
  1856.            imul ebx
  1857.            shrd eax,edx,14
  1858.            add ebp,eax   ; bp = new z
  1859.  
  1860.            mov ecx,esi
  1861.            mov ebx,edi
  1862.  
  1863.            ret
  1864.  
  1865. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1866. ;
  1867. ; Fzrotate: fast single variable solve for object/point rotation along
  1868. ;           pre-calculated y plane
  1869. ;
  1870. ; In:
  1871. ;    EBX - x point
  1872. ;    ECX - y point
  1873. ;    EBP - z point
  1874. ;    ematrix - 32 bit rotation matrix - set up by "setsincose" routine
  1875. ;    precal1 - set up by set_precal147
  1876. ;    precal4 - set up by set_precal147
  1877. ;    precal7 - set up by set_precal147
  1878. ;
  1879. ; Out:
  1880. ;    ESI - z point
  1881. ;
  1882. ; Notes:
  1883. ; Fast solve for single matrix variable similar to erotate but uses frotate
  1884. ; plane matrix with precal147
  1885. ;
  1886. ; remember , matrix offsets are:
  1887. ;
  1888. ;  0 1 2     multiply those by 4 for the doublewords
  1889. ;  3 4 5
  1890. ;  6 7 8
  1891. ;
  1892. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1893.  
  1894.            align 16
  1895.  
  1896. fzsolve:
  1897.            mov eax,ematrix+32      ; solve z = bx(6)+cx(7)+bp(8)
  1898.            imul ebp
  1899.            shrd eax,edx,14
  1900.            mov esi,eax
  1901.            add esi,precal7
  1902.            mov eax,ematrix+24
  1903.            imul ebx
  1904.            shrd eax,edx,14
  1905.            add esi,eax   ; si = new z
  1906.            ret
  1907.  
  1908. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1909. ;
  1910. ; Fxrotate: fast single variable solve for object/point rotation along
  1911. ;           pre-calculated y plane
  1912. ;
  1913. ; In:
  1914. ;    EBX - x point
  1915. ;    ECX - y point
  1916. ;    EBP - z point
  1917. ;    ematrix - 32 bit rotation matrix - set up by "setsincose" routine
  1918. ;    precal1 - set up by set_precal147
  1919. ;    precal4 - set up by set_precal147
  1920. ;    precal7 - set up by set_precal147
  1921. ;
  1922. ; Out:
  1923. ;    EDI - x point
  1924. ;
  1925. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1926.  
  1927.            align 16
  1928. fxsolve:
  1929.            mov eax,ematrix+8        ; solve x = bx(0)+cx(1)+bp(2)
  1930.            imul ebp
  1931.            shrd eax,edx,14
  1932.            mov edi,eax
  1933.            if usez eq yes
  1934.            add edi,precal1
  1935.            endif
  1936.            mov eax,ematrix+0
  1937.            imul ebx
  1938.            shrd eax,edx,14
  1939.            add edi,eax   ; di = new x
  1940.            ret
  1941.  
  1942. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1943. ;
  1944. ; Fyrotate: fast single variable solve for object/point rotation along
  1945. ;           pre-calculated y plane
  1946. ;
  1947. ; In:
  1948. ;    EBX - x point
  1949. ;    ECX - y point
  1950. ;    EBP - z point
  1951. ;    ematrix - 32 bit rotation matrix - set up by "setsincose" routine
  1952. ;    precal1 - set up by set_precal147
  1953. ;    precal4 - set up by set_precal147
  1954. ;    precal7 - set up by set_precal147
  1955. ;    ESI - z point
  1956. ;    EDI - x point
  1957. ; Out:
  1958. ;    EBX - x point
  1959. ;    ECX - y point
  1960. ;    EBP - z point
  1961. ;
  1962. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1963.  
  1964.            align 16
  1965. fysolve:
  1966.            mov eax,ematrix+20       ; solve y = bx(3)+cx(4)+bp(5)
  1967.            imul ebp
  1968.            shrd eax,edx,14
  1969.            mov ecx,eax
  1970.            add ecx,precal4
  1971.            mov eax,ematrix+12
  1972.            imul ebx
  1973.            shrd eax,edx,14
  1974.            add ecx,eax   ; cx = new y
  1975.  
  1976.            mov ebx,edi
  1977.            mov ebp,esi
  1978.  
  1979.            ret
  1980.  
  1981. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1982. ;
  1983. ; Lambert: generate lambert shading 1x3 matrix, completed in 6 imuls
  1984. ;
  1985. ; In:
  1986. ;    ESI - Object # to get angles from
  1987. ;    vxs[esi*2] - object x angle (0-65536)
  1988. ;    vys[esi*2] - object y angle (0-65536)
  1989. ;    vzs[esi*2] - object z angle (0-65536)
  1990. ;    y_angle_of_sun - (0-65536)
  1991. ;
  1992. ; Out:
  1993. ;    lmatrix  - shading matrix
  1994. ;    ESI - ?
  1995. ;
  1996. ; Notes:
  1997. ;
  1998. ;z= ( sz ( cx + ( sx * cy )) + cz * sy ) * 45degrees  [x]
  1999. ;   ( cz ( cx + ( sx * cy )) - sz * sy ) * 45degrees  [y]
  2000. ;   ( cx * cy - sx ) * 45 degrees                     [z]
  2001. ;
  2002. ;note cos45=sin45=2d41h, but we will use 2d00h (99.2% accurate)
  2003. ; you can change the y angle of the sun/light but not the x angle.
  2004. ; changing the x angle would require a new formula.
  2005. ;
  2006. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2007.  
  2008. lambert:
  2009.            mov ax,vxs[esi*2]
  2010.            neg ax
  2011.            push eax
  2012.            call cosign
  2013.            mov vcosx,eax
  2014.            pop eax
  2015.            call sign
  2016.            mov vsinx,eax
  2017.            mov ebp,eax            ; ebp = sx
  2018.  
  2019.            mov ax,vzs[esi*2]
  2020.            neg ax
  2021.            push eax
  2022.            call cosign
  2023.            mov vcosz,eax
  2024.            mov edi,eax            ; edi = cz
  2025.            pop eax
  2026.            call sign
  2027.            mov vsinz,eax
  2028.            mov edx,eax            ; edx = sz
  2029.  
  2030.            mov ax,vys[esi*2]
  2031.            neg ax
  2032.            add eax,y_angle_of_sun ; 2000h = 45 degrees y angle for light source
  2033.            push eax
  2034.            call cosign
  2035.            mov vcosy,eax
  2036.            mov esi,eax            ; esi = cy
  2037.            pop eax
  2038.            call sign
  2039.            mov vsiny,eax          ; eax = sy
  2040.  
  2041.            mov ebx,edx            ; ebx = sz
  2042.  
  2043.            mov ecx,eax            ; ecx = sy
  2044.  
  2045.            mov eax,ebp            ; get sx
  2046.  
  2047.            imul esi               ; eax = sx * cy
  2048.            shrd eax,edx,14
  2049.            sub eax,vcosx          ; eax = cx + ( sx * cy)
  2050.  
  2051.            push eax
  2052.  
  2053.            imul ebx               ; cx + ( sx * cy) * sz
  2054.            shrd eax,edx,14
  2055.            mov lmatrix+0,eax
  2056.  
  2057.            pop eax
  2058.  
  2059.            imul edi               ; di = cz
  2060.            shrd eax,edx,14
  2061.            mov lmatrix+4,eax      ; cx + ( sx * cy) * cz
  2062.  
  2063.            mov eax,ebx
  2064.            imul ecx               ; - sz * sy
  2065.            shrd eax,edx,14
  2066.            sub lmatrix+4,eax
  2067.  
  2068.            mov eax,edi
  2069.            imul ecx               ; cz * sy
  2070.            shrd eax,edx,14
  2071.            add lmatrix+0,eax
  2072.  
  2073.            mov eax,vcosx          ; (cx * cy - sx) * 45deg
  2074.            imul esi
  2075.            shrd eax,edx,14
  2076.            mov ebx,eax
  2077.            add ebx,ebp
  2078.  
  2079.            cmul eax,ebx,2d00h     ; * 45degrees
  2080.            shrd eax,edx,14
  2081.            movsx eax,ax
  2082.            mov lmatrix+8,eax
  2083.  
  2084.            mov ebx,lmatrix+4
  2085.            cmul eax,ebx,2d00h
  2086.            shrd eax,edx,14
  2087.            mov lmatrix+4,eax
  2088.  
  2089.            mov ebx,lmatrix+0
  2090.            cmul eax,ebx,2d00h
  2091.            shrd eax,edx,14
  2092.            mov lmatrix+0,eax
  2093.  
  2094.            ret
  2095.  
  2096. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2097. ;
  2098. ; Pre_cal_lambert: Pre-calculate all neccessary stuff for object DI
  2099. ;
  2100. ; In:
  2101. ;    EDI - Object # to pre-calculate normals for
  2102. ;    objbase[esi*4] -> offset of object data
  2103. ; Out:
  2104. ;    ESI -> minimum address of object data
  2105. ;    EDI -> maximum address of object data
  2106. ;    EBP -> points to header for object
  2107. ;
  2108. ; Notes:
  2109. ;
  2110. ; Precalculate surface normals for object di.  This  is  so  you  don't
  2111. ; have to type them in when designing new objects. Imagine, 400 points,
  2112. ; with 350 surfaces, calculating them all manually?  This routine  also
  2113. ; figures out the iteration skip offset (if you have surfaces dependant
  2114. ; on other surfaces) and also sets bit 1 if it is a line (two  points),
  2115. ; and sets bit 4 if 1 point.This routine also sets the number of points
  2116. ; to skip if an iteration is found. It  counts  the  number  of  points
  2117. ; within iterations (even iterations within iterations)  and  sets  the
  2118. ; skip value so any iterations skipped will have a pre-calculated point
  2119. ; offset.  Did that make sense?
  2120. ;
  2121. ; Things done here:
  2122. ;
  2123. ; set point command if only 1 connection
  2124. ; set line  command if only 2 connections
  2125. ; set normal bit in commands if shading used in texture
  2126. ; calculate and set shading normals
  2127. ; calculate offsets for iteration jumps (in case surface not visible)
  2128. ; calculate number of points to skip for iterations (in case surface not visible)
  2129. ; set offset flag if iteration uses a point offset (4'th future use word)
  2130. ; calculate and set auto-intensity of color if auto_s bit set
  2131. ;
  2132. ; Most of the above is done so the user (you) wont have to calculate this stuff
  2133. ; yourself - makes object modification much easier.
  2134. ;
  2135. ; If you find the routine to be sloppy remember it is only used
  2136. ; for object initialization.
  2137. ;
  2138. ; This routine  will probably crash if your object is not set up correctly
  2139. ; The entire 3dvect source will crash if this routine  isn't run  and  the
  2140. ; chances of you knowing how to do all that  this  routine  does  manually
  2141. ; are pretty slim since most of you out there are doughheads.
  2142. ;
  2143. ; The minimum and maximum addresses are returned in ESI and EDI so you can
  2144. ; output the resulting object to a binary file. EBP points to the starting
  2145. ; header of the object (usually, but not neccessaraly, the minimum address)
  2146. ;
  2147. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2148.  
  2149. lx1  dd 0
  2150. ly1  dd 0
  2151. lz1  dd 0
  2152.  
  2153. lx2  dd 0
  2154. ly2  dd 0
  2155. lz2  dd 0
  2156.  
  2157. lx3  dd 0
  2158. ly3  dd 0
  2159. lz3  dd 0
  2160.  
  2161. finx dd 0
  2162. finy dd 0
  2163. finz dd 0
  2164.  
  2165. temp1 dw 0
  2166. temp2 dw 0 ; number of points
  2167. temp3 dw 0 ; number of sides
  2168. temp4 dw 0
  2169. temp5 dd 0 ; minimum address
  2170. temp6 dd 0 ; maximum address
  2171.  
  2172. pre_cal_lambert:
  2173.            movzx edi,di           ; in case user is lazy
  2174.            mov esi,objbase[edi*4]
  2175.            mov temp5,esi
  2176.            mov temp6,esi
  2177.            push esi               ; save for exit
  2178. more_reses:
  2179.            push esi               ; save header offset
  2180.            add esi,4
  2181.            lodsd
  2182.            add esi,eax            ; handle first resolution
  2183.  
  2184.            lodsw
  2185.            mov temp2,ax
  2186.            lodsw
  2187.            mov temp3,ax
  2188.  
  2189.            mov xad,0
  2190.            mov yad,0
  2191.            mov zad,0
  2192.            mov temp1,-1
  2193.            mov ax,[esi+14]
  2194.            mov temp4,ax
  2195.  
  2196.            mov eax,[esi+8*2]
  2197.            or eax,[esi+8*2+4]
  2198.            jnz lam_hhgg
  2199.            mov dword ptr [esi+8*2],maxz    ; if no max/min found, force one
  2200.            mov dword ptr [esi+8*2+4],minz
  2201. lam_hhgg:
  2202.            mov eax,[esi+12*2]
  2203.            jnz lam_hhgc
  2204.            mov dword ptr [esi+12*2],tolerance
  2205. lam_hhgc:
  2206.            add esi,25*2           ; skip future use bytes
  2207.  
  2208.            mov edi,4              ; edi=2 to skip center of gravity
  2209.            mov xp,0
  2210.            mov yp,0
  2211.            mov zp,0
  2212.            cmp temp2,0
  2213.            je no_points_2
  2214. lam_ap12:
  2215.            mov bx,w [esi]         ; load all the points into array
  2216.            mov cx,w [esi+2]
  2217.            mov bp,w [esi+4]
  2218.            add bx,w xad
  2219.            add cx,w yad
  2220.            add bp,w zad
  2221.            movsx ebx,bx
  2222.            movsx ecx,cx
  2223.            movsx ebp,bp
  2224.            mov xp[edi],ebx
  2225.            mov yp[edi],ecx
  2226.            mov zp[edi],ebp
  2227.            add esi,6
  2228.            add edi,4
  2229.            dec temp2
  2230.            jne s lam_ap12         ; esi = address of sides now...
  2231. no_points_2:
  2232.            mov pointindex,edi
  2233.  
  2234. lam_loadsides:
  2235.            call checkesi          ; check minimum and maximum addresses
  2236.  
  2237.            mov edi,esi            ; save in case of line adjust
  2238.            mov ax,[esi]           ; get command
  2239.  
  2240.            mov bx,ax              ; save command
  2241.            test ax,special        ; test if special command
  2242.            jz s lam_notmap        ; no, skip through loop
  2243.            mov di,ax
  2244.            and edi,special-1
  2245.  
  2246.            cmp ax,gosub           ; check for jump commands, yeah,yeah, I should have made a table, who cares...
  2247.            jne ffgg1
  2248.            add esi,2
  2249.            lodsw
  2250.            push esi
  2251.            movsx eax,ax
  2252.            sub esi,2
  2253.            add esi,eax
  2254.            jmp lam_next
  2255. ffgg1:
  2256.            cmp ax,return
  2257.            jne ffgg2
  2258.            pop esi
  2259.            jmp lam_next
  2260. ffgg2:
  2261.            cmp ax,goto_offset
  2262.            jne ffgg3
  2263.            add esi,2
  2264.            lodsw
  2265.            movsx eax,ax
  2266.            sub esi,2
  2267.            add esi,eax
  2268.            jmp lam_next
  2269. ffgg3:
  2270.            mov di,number_ofb[edi*2] ; yes, skip special command length
  2271.            add esi,edi
  2272.            mov bx,0
  2273.            cmp ax,sub_object
  2274.            je lam_do_it
  2275.            cmp ax,static_sub_object
  2276.            je lam_do_it
  2277.            jmp lam_next           ; go to next side
  2278. lam_notmap:
  2279.            call pcl_testashade
  2280.  
  2281.            mov ax,[esi+2]         ; get texture for both sides
  2282.            or  ax,[esi+4]
  2283.  
  2284.            test ax,shade          ; test shading bit
  2285.            jnz lam_calcit         ; yes, calculate shading normal
  2286.  
  2287.            push edi               ; save command location
  2288.  
  2289.            add esi,4+4+2          ; skip 2 colour & 2 texture words & command
  2290.            mov edi,esi
  2291.  
  2292.            lodsw                  ; get first point indexer
  2293.            add ax,temp4
  2294.            stosw
  2295.  
  2296.            mov cx,ax
  2297.            mov dx,0
  2298. lam_ldlp:
  2299.            lodsw                  ; count number of connection points
  2300.            add ax,temp4
  2301.            stosw
  2302.  
  2303.            inc dx
  2304.            cmp ax,cx
  2305.            jne lam_ldlp
  2306.  
  2307.            call checkesi          ; check minimum and maximum addresses
  2308.  
  2309.            pop edi                ; pop command location
  2310.  
  2311.            cmp dx,1               ; only 1 point?, set point command
  2312.            jne lam_test_line
  2313.            or  w [edi+0],both
  2314.            or  w [edi+2],point
  2315.            or  w [edi+4],point
  2316.            jmp lam_test_iteration
  2317.  
  2318. lam_test_line:
  2319.            cmp dx,2               ; only 2 points?, set line command
  2320.            jne lam_test_iteration
  2321.            or  w [edi+0],both
  2322.            or  w [edi+2],line
  2323.            or  w [edi+4],line
  2324.  
  2325. lam_test_iteration:
  2326.            mov ax,0
  2327.            test bx,iterate        ; test if iteration command used
  2328.            jnz lam_do_it          ; yes,solve internal iteration
  2329. lam_next:
  2330.            dec temp1
  2331.            jnz lam_nopop
  2332.            pop ax
  2333.            mov temp4,ax
  2334.            pop ax
  2335.            mov temp1,ax
  2336.            jmp lam_next
  2337. lam_nopop:
  2338.            dec temp3
  2339.            jnz lam_loadsides
  2340.  
  2341.            pop esi
  2342.            lodsd
  2343.            add esi,4
  2344.            cmp eax,-1             ; last resolution?
  2345.            jne more_reses
  2346.  
  2347.            call checkesi          ; check minimum and maximum addresses
  2348.            pop ebp                ; pop header offset
  2349.            mov esi,temp5          ; load up start and end offsets of object
  2350.            mov edi,temp6
  2351.  
  2352.            ret
  2353.  
  2354. lam_calcit:
  2355.            push esi               ; save command location
  2356.            add esi,4+4+2          ; skip colour and 2 future use words
  2357.  
  2358.            lodsw                  ; first point
  2359.            add ax,temp4
  2360.            mov [esi-2],ax
  2361.            push ax
  2362.            movzx edi,ax
  2363.            shl edi,2
  2364.  
  2365.            mov ebx,[xp+edi]
  2366.            mov ecx,[yp+edi]
  2367.            mov ebp,[zp+edi]
  2368.  
  2369.            mov lx1,ebx
  2370.            mov ly1,ecx
  2371.            mov lz1,ebp
  2372.  
  2373.            lodsw                  ; second point
  2374.            add ax,temp4
  2375.            mov [esi-2],ax
  2376.            movzx edi,ax
  2377.            shl edi,2
  2378.  
  2379.            mov ebx,[xp+edi]
  2380.            mov ecx,[yp+edi]
  2381.            mov ebp,[zp+edi]
  2382.  
  2383.            mov lx2,ebx
  2384.            mov ly2,ecx
  2385.            mov lz2,ebp
  2386.  
  2387.            lodsw                  ; third point
  2388.            add ax,temp4
  2389.            mov [esi-2],ax
  2390.            movzx edi,ax
  2391.            shl edi,2
  2392.  
  2393.            mov ebx,[xp+edi]
  2394.            mov ecx,[yp+edi]
  2395.            mov ebp,[zp+edi]
  2396.  
  2397.            mov lx3,ebx
  2398.            mov ly3,ecx
  2399.            mov lz3,ebp
  2400.  
  2401.            push esi
  2402.  
  2403.            call calc_normal
  2404.  
  2405.            pop esi
  2406.  
  2407.            pop dx                 ; now find shading normal storage, pop first connector
  2408.  
  2409. lam_ldl2:
  2410.            lodsw
  2411.            add ax,temp4
  2412.            mov [esi-2],ax
  2413.            cmp ax,dx
  2414.            jne lam_ldl2
  2415.  
  2416.            mov edi,esi
  2417.  
  2418.            mov ax,bx
  2419.            stosw
  2420.            mov ax,cx
  2421.            stosw
  2422.            mov ax,bp
  2423.            stosw
  2424.  
  2425.            add esi,6
  2426.  
  2427.            pop edi         ; get original command location back
  2428.            or w [edi],normal
  2429.            mov bx,[edi]
  2430.            jmp lam_test_iteration
  2431.  
  2432. lam_surfc_cnt dw 0
  2433.  
  2434. ; this finds the total number of points to skip if an iteration fails, dx = #
  2435. ; remember, this is a pre-calculation routine so it doesn't need to be fast.
  2436.  
  2437. lam_do_it:
  2438.            mov dx,0        ; clear total number of points to skip
  2439.  
  2440.            mov ax,[esi+10]        ; test if there is a center of rotation point
  2441.            or ax,[esi+12]
  2442.            or ax,[esi+14]
  2443.            jz done_alter2
  2444.            or w [esi+8],centroid  ; set flag if offset found (center of gravity)
  2445.  
  2446.            movsx ebx,w [esi+10]
  2447.            movsx ecx,w [esi+12]
  2448.            movsx ebp,w [esi+14]
  2449.            add xad,ebx
  2450.            add yad,ecx
  2451.            add zad,ebp
  2452.            mov ebx,xad
  2453.            mov ecx,yad
  2454.            mov ebp,zad
  2455.            mov edi,pointindex
  2456.            mov xp[edi],ebx
  2457.            mov yp[edi],ecx
  2458.            mov zp[edi],ebp
  2459.            add pointindex,2
  2460.            add dx,1        ; centroid is an extra point to skip
  2461. done_alter2:
  2462.            mov ax,temp1
  2463.            push ax
  2464.            mov ax,temp4
  2465.            push ax
  2466.  
  2467.            mov ax,[esi+18]
  2468.            add temp4,ax
  2469.            mov w [esi+18],0
  2470.  
  2471.            mov lam_surfc_cnt,0
  2472.            push esi        ; this is our return address (continue from here+4)
  2473.  
  2474.            lodsw           ; get number of points.
  2475.            add dx,ax       ; save as TOTAL number of points to skip
  2476.            mov temp2,ax
  2477.  
  2478.            lodsw           ; get number of surfaces
  2479.            mov temp1,ax
  2480.            inc temp1
  2481.            add lam_surfc_cnt,ax ; count until this is zero
  2482.  
  2483.            mov eax,[esi+8*2]
  2484.            or eax,[esi+10*2]
  2485.            jnz lam_hhgg2
  2486.            mov dword ptr [esi+8*2],maxz  ; if no max/min found, force one
  2487.            mov dword ptr [esi+8*2+4],minz
  2488. lam_hhgg2:
  2489.            mov eax,[esi+12*2]
  2490.            jnz lam_hhgl
  2491.            mov dword ptr [esi+12*2],tolerance
  2492. lam_hhgl:
  2493.            add esi,25*2
  2494.  
  2495.            mov edi,pointindex
  2496.            cmp temp2,0
  2497.            je lam_test_check      ; only sides added, no additional points
  2498. lam_ap13:
  2499.            mov bx,w [esi]         ; load all the points into array
  2500.            mov cx,w [esi+2]       ; for calculation of gourad shadings
  2501.            mov bp,w [esi+4]
  2502.            add bx,w xad
  2503.            add cx,w yad
  2504.            add bp,w zad
  2505.            movsx ebx,bx
  2506.            movsx ecx,cx
  2507.            movsx ebp,bp
  2508.            mov xp[edi],ebx
  2509.            mov yp[edi],ecx
  2510.            mov zp[edi],ebp
  2511.            add esi,6
  2512.            add edi,4
  2513.            dec temp2
  2514.            jne s lam_ap13         ; esi = address of sides now...
  2515.  
  2516.            mov pointindex,edi
  2517.  
  2518. lam_test_check:
  2519.            cmp lam_surfc_cnt,0    ; test if user just wants to add points
  2520.            je lam_no_surfs        ; i dont know why anyone would want to do this?
  2521.  
  2522. lam_test_until_target:
  2523.            lodsw                  ; get command
  2524.            mov bx,ax
  2525.            test ax,special        ; test if special command
  2526.            jz s lam_notmap_it     ; no, skip through loop
  2527.  
  2528.            mov di,ax
  2529.            and edi,special-1
  2530.  
  2531.            cmp ax,gosub           ; check for jump commands, yeah,yeah, I should have made a table, who cares...
  2532.            jne ffgg1x
  2533.            add esi,2
  2534.            lodsw
  2535.            push esi
  2536.            movsx eax,ax
  2537.            sub esi,2
  2538.            add esi,eax
  2539.            jmp lam_next_it
  2540. ffgg1x:
  2541.            cmp ax,return
  2542.            jne ffgg2x
  2543.            pop esi
  2544.            jmp lam_next_it
  2545. ffgg2x:
  2546.            cmp ax,goto_offset
  2547.            jne ffgg3x
  2548.            add esi,2
  2549.            lodsw
  2550.            movsx eax,ax
  2551.            sub esi,2
  2552.            add esi,eax
  2553.            jmp lam_next_it
  2554. ffgg3x:
  2555.            movzx edi,number_ofb[edi*2] ; yes, skip special command length
  2556.            add esi,edi
  2557.            sub esi,2
  2558.            cmp ax,sub_object
  2559.            je lam_re_lam
  2560.            cmp ax,static_sub_object
  2561.            je lam_re_lam
  2562.            jmp s lam_nog
  2563.  
  2564. lam_notmap_it:
  2565.            lodsw
  2566.            mov bp,ax
  2567.            lodsw
  2568.            or bp,ax               ; find if shading bit used, add esi,6 if so
  2569.            add esi,4              ; skip 2 colour words
  2570.  
  2571.            lodsw                  ; get first point indexer
  2572.            mov cx,ax
  2573. lam_ldl3:
  2574.            lodsw
  2575.            cmp ax,cx
  2576.            jne lam_ldl3
  2577.  
  2578.            test bp,shade          ; test if gouraud normal present
  2579.            jz lam_nog
  2580.            add esi,6              ; skip it if present
  2581. lam_nog:
  2582.            test bx,iterate        ; test if iteration command used
  2583.            jnz lam_re_lam         ; solve internal iteration again...
  2584. lam_next_it:
  2585.            dec lam_surfc_cnt
  2586.            jnz lam_test_until_target
  2587. lam_no_surfs:
  2588.            mov edi,esi            ; save current location
  2589.            pop esi                ; return original start location
  2590.            sub edi,esi            ; get difference between them
  2591.            sub di,8               ; offset for loadsides routine - constant
  2592.  
  2593.            lodsw                  ; get number of points
  2594.            mov bx,ax
  2595.  
  2596.            lodsw
  2597.            add temp3,ax
  2598.  
  2599.            mov cx,dx
  2600.            mov ax,6
  2601.            imul bx
  2602.            movzx ebx,ax
  2603.  
  2604.            mov ax,di
  2605.            mov edi,esi
  2606.            stosw                  ; save offset
  2607.            mov ax,cx
  2608.            stosw                  ; save number of points found in iterations
  2609.  
  2610.            mov eax,[esi+8*2]
  2611.            or eax,[esi+10*2]
  2612.            jnz lam_hhgg3
  2613.            mov dword ptr [esi+8*2],maxz  ; if no max/min found, force one
  2614.            mov dword ptr [esi+8*2+4],minz
  2615. lam_hhgg3:
  2616.            mov eax,[esi+12*2]
  2617.            jnz lam_hhgq
  2618.            mov dword ptr [esi+12*2],tolerance
  2619. lam_hhgq:
  2620.            add esi,25*2           ; adjust for next load
  2621.            add esi,ebx
  2622.  
  2623.            jmp lam_next
  2624.  
  2625. lam_re_lam:
  2626.            lodsw           ; get number of points for recursed iteration
  2627.            add dx,ax       ; save as TOTAL number of points to skip
  2628.            mov cx,ax
  2629.  
  2630.            lodsw           ; get number of surfaces
  2631.            add lam_surfc_cnt,ax ; count until this is zero
  2632.  
  2633.            mov eax,[esi+8*2]
  2634.            or eax,[esi+10*2]
  2635.            jnz lam_hhgg4
  2636.            mov dword ptr [esi+8*2],maxz  ; if no max/min found, force one
  2637.            mov dword ptr [esi+8*2+4],minz
  2638. lam_hhgg4:
  2639.            mov eax,[esi+12*2]
  2640.            jnz lam_hhgv
  2641.            mov dword ptr [esi+12*2],tolerance
  2642. lam_hhgv:
  2643.            add esi,25*2
  2644.  
  2645.            mov eax,6
  2646.            imul cx
  2647.            add esi,eax
  2648.  
  2649.            jmp lam_next_it
  2650.  
  2651. checkesi:
  2652.            cmp esi,temp5
  2653.            jae noesi1
  2654.            mov temp5,esi
  2655. noesi1:
  2656.            cmp esi,temp6
  2657.            jbe noesi2
  2658.            mov temp6,esi
  2659. noesi2:
  2660.            ret
  2661.  
  2662. pcl_testashade:
  2663.            mov ax,[esi+2]
  2664.            or  ax,[esi+4]
  2665.            test ax,auto_s
  2666.            jnz pcl_test2
  2667.            ret
  2668. pcl_test2:
  2669.            pushad
  2670.            push esi
  2671.            push esi
  2672.            mov vxs,0
  2673.            mov vys,0
  2674.            mov vzs,0
  2675.            mov esi,0
  2676.            call lambert
  2677.            pop esi
  2678.  
  2679.            movzx ebx,w [esi+10]
  2680.            movzx ecx,w [esi+12]
  2681.            movzx edx,w [esi+14]
  2682.  
  2683.            mov eax,xp[ebx]
  2684.            mov lx1,eax
  2685.            mov eax,yp[ebx]
  2686.            mov ly1,eax
  2687.            mov eax,zp[ebx]
  2688.            mov lz1,eax
  2689.            mov eax,xp[ecx]
  2690.            mov lx2,eax
  2691.            mov eax,yp[ecx]
  2692.            mov ly2,eax
  2693.            mov eax,zp[ecx]
  2694.            mov lz2,eax
  2695.            mov eax,xp[edx]
  2696.            mov lx3,eax
  2697.            mov eax,yp[edx]
  2698.            mov ly3,eax
  2699.            mov eax,zp[edx]
  2700.            mov lz3,eax
  2701.            call calc_normal
  2702.  
  2703.            call lrotate
  2704.            pop esi
  2705.            push edi
  2706.  
  2707.            test w [esi+2],auto_s
  2708.            jz pcl_test4
  2709.            test w [esi+2],inverse
  2710.            jz pcl_test3
  2711.            neg edi
  2712. pcl_test3:
  2713.            add edi,256
  2714.            shr edi,1              ; result -256 to +256, turn into 0-256
  2715.            mov al,b shading_tables[edi] ; now into 0-15
  2716.            xor ah,ah
  2717.            add w [esi+6],ax
  2718.            mov ax,[esi+2]
  2719.            and ax,65535-auto_s
  2720.            mov [esi+2],ax
  2721. pcl_test4:
  2722.            pop edi
  2723.  
  2724.            test w [esi+4],auto_s
  2725.            jz pcl_test6
  2726.            test w [esi+4],inverse
  2727.            jz pcl_test5
  2728.            neg edi
  2729. pcl_test5:
  2730.            add edi,256
  2731.            shr edi,1              ; result -256 to +256, turn into 0-256
  2732.            mov al,b shading_tables[edi] ; now into 0-15
  2733.            xor ah,ah
  2734.            add w [esi+8],ax
  2735.            mov ax,[esi+4]
  2736.            and ax,65535-auto_s
  2737.            mov [esi+4],ax
  2738. pcl_test6:
  2739.            popad
  2740.            ret
  2741.  
  2742. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2743. ;
  2744. ; Calc_normal: calculate surface normal
  2745. ;
  2746. ; In:
  2747. ;    LX1 - x of point 1 on triangle
  2748. ;    LY1 - y of point 1 on triangle
  2749. ;    LZ1 - z of point 1 on triangle
  2750. ;    LX2 - x of point 2 on triangle
  2751. ;    LY2 - y of point 2 on triangle
  2752. ;    LZ2 - z of point 2 on triangle
  2753. ;    LX3 - x of point 3 on triangle
  2754. ;    LY3 - y of point 3 on triangle
  2755. ;    LZ3 - z of point 3 on triangle
  2756. ;
  2757. ; Out:
  2758. ;    EBX = finx = x of surface normal of triangle
  2759. ;    ECX = finy = y of surface normal of triangle
  2760. ;    EBP = finz = z of surface normal of triangle
  2761. ;
  2762. ; Notes:
  2763. ; x2 = x2 - x1
  2764. ; y2 = y2 - y1
  2765. ; z2 = z2 - z1
  2766. ;
  2767. ; x3 = x3 - x1
  2768. ; y3 = y3 - y1
  2769. ; z3 = z3 - z1
  2770. ;
  2771. ; x = y2 * z3 - z2 * y3
  2772. ; y = z2 * x3 - x2 * z3
  2773. ; z = x2 * y3 - y2 * x3
  2774. ;
  2775. ; a = SQR(x ^ 2 + y ^ 2 + z ^ 2)
  2776. ;
  2777. ; x = INT(x / a * 256 + .5)
  2778. ; y = INT(y / a * 256 + .5)
  2779. ; z = INT(z / a * 256 + .5)
  2780. ;
  2781. ; This worked for me on the first try!
  2782. ;
  2783. ; If you wanted to get the equation of a plane, you could do this after:
  2784. ;  d = - x * x1 - y * y1 - z * z1
  2785. ;
  2786. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2787.  
  2788.            nshl = 8
  2789.  
  2790. calc_normal:
  2791.            mov ebx,lx1
  2792.            mov ecx,ly1
  2793.            mov ebp,lz1
  2794.  
  2795.            sub lx2,ebx
  2796.            sub ly2,ecx
  2797.            sub lz2,ebp
  2798.  
  2799.            sub lx3,ebx
  2800.            sub ly3,ecx
  2801.            sub lz3,ebp
  2802.  
  2803.            mov eax,ly2
  2804.            mov ebx,lz3
  2805.            imul ebx
  2806.            mov ecx,eax
  2807.  
  2808.            mov eax,lz2
  2809.            mov ebx,ly3
  2810.            imul ebx
  2811.            sub ecx,eax
  2812.  
  2813.            mov finx,ecx ; save x of normal
  2814.  
  2815.            mov eax,lz2
  2816.            mov ebx,lx3
  2817.            imul ebx
  2818.            mov ecx,eax
  2819.  
  2820.            mov eax,lx2
  2821.            mov ebx,lz3
  2822.            imul ebx
  2823.            sub ecx,eax
  2824.  
  2825.            mov finy,ecx ; save y of normal
  2826.  
  2827.            mov eax,lx2
  2828.            mov ebx,ly3
  2829.            imul ebx
  2830.            mov ecx,eax
  2831.  
  2832.            mov eax,ly2
  2833.            mov ebx,lx3
  2834.            imul ebx
  2835.            sub ecx,eax
  2836.  
  2837.            mov finz,ecx ; save z of normal
  2838.  
  2839. calc_testloop:
  2840.            cmp finx,32768 ; make sure (normal^2)*2 is < 2^32
  2841.            jge calc_shrit
  2842.            cmp finy,32768
  2843.            jge calc_shrit
  2844.            cmp finz,32768
  2845.            jge calc_shrit
  2846.  
  2847.            cmp finx,-32768
  2848.            jle calc_shrit
  2849.            cmp finy,-32768
  2850.            jle calc_shrit
  2851.            cmp finz,-32768
  2852.            jg  ok_2_bite_dust
  2853.  
  2854. calc_shrit:
  2855.            shr finx,1   ; calculations will be too large if squared, div by 2
  2856.            test finx,40000000h
  2857.            jz no_neg_calc1
  2858.            or   finx,80000000h
  2859. no_neg_calc1:
  2860.            shr finy,1
  2861.            test finy,40000000h
  2862.            jz no_neg_calc2
  2863.            or   finy,80000000h
  2864. no_neg_calc2:
  2865.            shr finz,1
  2866.            test finz,40000000h
  2867.            jz no_neg_calc3
  2868.            or   finz,80000000h
  2869. no_neg_calc3:
  2870.            jmp calc_testloop
  2871.  
  2872. ok_2_bite_dust:
  2873.            mov eax,finx ; x^2
  2874.            mov edi,eax  ; objects
  2875.            imul edi
  2876.            mov edi,eax
  2877.  
  2878.            mov eax,finy ; y^2
  2879.            mov esi,eax
  2880.            imul esi
  2881.            mov esi,eax
  2882.  
  2883.            mov eax,finz ; z^2
  2884.            mov ebp,eax
  2885.            imul ebp
  2886.  
  2887.            add eax,esi
  2888.            add eax,edi
  2889.  
  2890.            call sqrt    ; get square root of number
  2891.  
  2892.            mov ecx,eax
  2893.            cmp ecx,0
  2894.            je lam_abort ; should never happen!
  2895.  
  2896.            mov eax,finx
  2897.            cdq
  2898.            shl eax,nshl ; set unit vector to 2^nshl (256)
  2899.            idiv ecx
  2900.            mov finx,eax
  2901.  
  2902.            mov eax,finy
  2903.            cdq
  2904.            shl eax,nshl
  2905.            idiv ecx
  2906.            mov finy,eax
  2907.  
  2908.            mov eax,finz
  2909.            cdq
  2910.            shl eax,nshl
  2911.            idiv ecx
  2912.            mov finz,eax
  2913.  
  2914.            mov ebx,finx
  2915.            mov ecx,finy
  2916.            mov ebp,finz
  2917.  
  2918. lam_abort:
  2919.            ret
  2920.  
  2921. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2922. ; Calc_D: Calculate D portion of equation of a plane
  2923. ; In:
  2924. ;    EBX = x of surface normal of triangle
  2925. ;    ECX = y of surface normal of triangle
  2926. ;    EBP = z of surface normal of triangle
  2927. ;    LX1 - x of point on triangle (any point)
  2928. ;    LY1 - y of point on triangle
  2929. ;    LZ1 - z of point on triangle
  2930. ; Out:
  2931. ;    EAX = D     (Ax+By+Cz=D)
  2932. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2933. calc_d:
  2934.            mov eax,lx1
  2935.            imul ebx
  2936.            mov esi,eax
  2937.  
  2938.            mov eax,ly1
  2939.            imul ecx
  2940.            add esi,eax
  2941.  
  2942.            mov eax,lz1
  2943.            imul ebp
  2944.            add eax,esi
  2945.  
  2946.            ret
  2947.  
  2948. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2949. ;
  2950. ; Set_up_all_lambert: set up all lambert normals from object si to object di
  2951. ;
  2952. ; In:
  2953. ;    ESI - object # to start at
  2954. ;    EDI - object # to end at
  2955. ;    objbase[esi*4 - edi*4] -> offsets to object data
  2956. ; Out:
  2957. ;   null
  2958. ;
  2959. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2960.  
  2961. set_up_all_lambert:
  2962.            movzx edi,di ; in case user is lazy
  2963.            movzx esi,si
  2964.  
  2965.            xchg edi,esi ; so user doesn't get confuzed
  2966. set_lop:
  2967.            push esi edi
  2968.            call pre_cal_lambert
  2969.            pop edi esi
  2970.            inc edi
  2971.            cmp edi,esi
  2972.            jna  set_lop
  2973.  
  2974.            ret
  2975.  
  2976. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2977. ;
  2978. ; Lrotate: rotate surface normal through lambert matrix
  2979. ;
  2980. ; In:
  2981. ;    BX - x of surface normal
  2982. ;    CX - y of surface normal
  2983. ;    BP - z of surface normal
  2984. ;    lmatrix - 16 bit, 1x3 lambert shading matrix - set up by "lambert" routine
  2985. ; Out:
  2986. ;    BX - x of surface normal (untouched)
  2987. ;    CX - y of surface normal (untouched)
  2988. ;    BP - z of surface normal (untouched)
  2989. ;   EDI - colour intensity for surface (-255 to +255)
  2990. ;
  2991. ; Notes:
  2992. ;   Your mother is a hamster.
  2993. ;
  2994. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2995.  
  2996. lrotate:
  2997.            mov eax,lmatrix+8    ; solve edi = bx(0)+cx(4)+bp(8)
  2998.            imul bp
  2999.            shrd ax,dx,14
  3000.            mov edi,eax
  3001.            mov eax,lmatrix+4
  3002.            imul cx
  3003.            shrd ax,dx,14
  3004.            add edi,eax
  3005.            mov eax,lmatrix+0
  3006.            imul bx
  3007.            shrd ax,dx,14
  3008.            add edi,eax          ; di = new colour -256 to 255 (not edi, di!)
  3009.            movsx edi,di
  3010.  
  3011.            add edi,256          ; make sure result is within range -256 to 256
  3012.            and edi,511          ; sometimes is messes up...
  3013.            sub edi,256
  3014.  
  3015.            ret
  3016.  
  3017. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3018. ;
  3019. ; Shading tables used for fake cosin colour intensity - 256 bytes
  3020. ; Default is 16 colours per lambert calculation.  But you could have 32, 48
  3021. ; or whatever you want, even an odd number like 53.  Use the SHADING.BAS
  3022. ; program to make the table to your custom size.
  3023. ;
  3024. ; Shading_bits is the variable for use with the texture command "LAST".  This
  3025. ; variable tells the routine what bits to  pluck  off  when  determining  the
  3026. ; shading intensity. Obviosly this cant  be  used  if  your  palette  shading
  3027. ; length is not a function of 2's complement.
  3028. ;
  3029. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3030.  
  3031.   if shading_colours eq 16
  3032.  
  3033. ; 16 colour shading table
  3034.  
  3035.   shading_bits equ 0fh
  3036.  
  3037.   align 16
  3038. shading_tables:
  3039.   db 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1
  3040.   db 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2
  3041.   db 2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3
  3042.   db 3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4
  3043.   db 4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5
  3044.   db 5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6
  3045.   db 6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7
  3046.   db 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
  3047.   db 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
  3048.   db 8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9
  3049.   db 9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10
  3050.   db 10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11
  3051.   db 11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12
  3052.   db 12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13
  3053.   db 13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14
  3054.   db 14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15
  3055.  
  3056.   elseif shading_colours eq 32
  3057.  
  3058. ; 32 colour shading table
  3059.  
  3060.   shading_bits equ 1fh
  3061.  
  3062.    align 16
  3063. shading_tables:
  3064.    db 0,0,0,0,0,0,0,1,1,1,1,1,1,1,2,2
  3065.    db 2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4
  3066.    db 4,4,4,4,5,5,5,5,5,5,5,5,6,6,6,6
  3067.    db 6,6,6,6,7,7,7,7,7,7,7,7,8,8,8,8
  3068.    db 8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10
  3069.    db 10,10,10,10,10,11,11,11,11,11,11,11,11,12,12,12
  3070.    db 12,12,12,12,12,12,13,13,13,13,13,13,13,13,14,14
  3071.    db 14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15
  3072.    db 16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17
  3073.    db 17,18,18,18,18,18,18,18,18,18,19,19,19,19,19,19
  3074.    db 19,19,20,20,20,20,20,20,20,20,20,21,21,21,21,21
  3075.    db 21,21,21,22,22,22,22,22,22,22,22,22,23,23,23,23
  3076.    db 23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25
  3077.    db 25,25,25,25,26,26,26,26,26,26,26,26,27,27,27,27
  3078.    db 27,27,27,28,28,28,28,28,28,28,29,29,29,29,29,29
  3079.    db 29,29,30,30,30,30,30,30,30,31,31,31,31,31,31,31
  3080.    endif
  3081.  
  3082. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3083. ;
  3084. ; Sqrax2bx2: Fast pathagorean solve, sqr(ax^2+bx^2)
  3085. ;
  3086. ; In:
  3087. ;   EAX - a number
  3088. ;   EBX - another number
  3089. ; Out:
  3090. ;   EAX - sqr(EAX^2+EBX^2)
  3091. ;
  3092. ; Notes:
  3093. ;
  3094. ; Works well for numbers eax<90, ebx<128.  Uses huge table.
  3095. ; Limit of solve is for 32 bit values. Only works for positive values of ax&bx
  3096. ; Numbers outside the limit of the tabel could be shr'd and re-tested rather
  3097. ; than using the mathematical solution. There should be a .BAS Qbasic file
  3098. ; that generates the table provided with the 3Dvect source.
  3099. ;
  3100. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3101.  
  3102. pathagorean:
  3103. ;          include pathagor.inc ; dont include this routine if you don't need it
  3104.                                 ; 'cause it's a real big table.
  3105. sqrax2bx2:
  3106.            cmp eax,ebx          ; set eax = smallest
  3107.            ja s pa_smal
  3108.            xchg eax,ebx
  3109. pa_smal:
  3110.            cmp eax,90           ; check if parameters of triangle are within
  3111.            jae s pa_imul        ; table or are too big for fast load.
  3112.            cmp ebx,128
  3113.            jae s pa_imul
  3114.  
  3115.            shl ebx,7            ; *128
  3116.            mov al,b pathagorean[eax+ebx]
  3117.            ret
  3118. pa_imul:
  3119.            imul eax,eax         ; variables too large, do mathematically
  3120.            imul ebx,ebx
  3121.            add eax,ebx
  3122.            jmp sqrt
  3123.  
  3124.